With GNU
find:
find . -name foo.mp4 -printf '%h\n'
With other find
s, provided directory names don't contain newline characters:
find . -name foo.mp4 |
LC_ALL=C sed 's|/[^/]*$||'
Or:
find . -name foo.mp4 -exec dirname {} \;
though that means forking a process and running one dirname
command per file.
If you need to run a command on that path
, you can do (standard syntax):
find . -name "featured.mp4" -exec sh -c '
for file do
dir=${file%/*}
ffmpeg -i "$file" -c:v libvpx -b:v 1M -c:a libvorbis "$dir" featured.webm
done' sh {} +
Though in this case, you may be able to use -execdir
(a BSD extension also available in GNU find
), which chdir()
s to the file's directory:
find . -name "featured.mp4" -execdir \
ffmpeg -i {} -c:v libvpx -b:v 1M -c:a libvorbis . featured.webm \;
Beware though that while the GNU implementation of find
will expand {}
to ./filename
here, BSD ones expand to filename
. It's OK here as the filename is passed as argument to an option and is always featured.mp4
anyway, but for other usages you may have to take into account that the file name may start with -
or +
(and be understood as an option by the command) or contain =
(and be understood as a variable assignment by awk for instance), or other characters causing this kind of problem with perl -p/n
(not all of them fixed by GNU find
's ./
prefix though in that case), etc.
-printf
%h
Leading directories of file's name (all but the last element). If the file name contains no slashes (since it is in the current directory) the %h specifier expands to ".". – Costas Jan 23 '15 at 10:32find ./ -name "foo.mp4" -printf "%h\n"
will print path to for each found file (one by line). More over as usual nobody use-exec echo {}
therefore there is-print
(default even omitted) orprintf
action. – Costas Jan 23 '15 at 10:45-printf
is GNU-only. The OP's mentioning OS/X (a BSD system). – Stéphane Chazelas Jan 23 '15 at 11:07