23

I have a parent folder named "parent_folder" with a lot of subfolders, in these subfolders is a file named "foo.mp4".

I can find these files easily by doing this:

mymacbook:parent_folder username$ find ./ -name "foo.mp4" -exec echo {} \;

Now that returns the path of each file, relative to parent_folder/

./path/to/foo.mp4

How can i return just the path, without the filename?

5
  • 1
    man find (ACTIONS): -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, 2015 at 10:32
  • Could you show an example of that? Should I put that behind '-exec' or before?
    – dubbelj
    Jan 23, 2015 at 10:36
  • 1
    find ./ -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) or printf action.
    – Costas
    Jan 23, 2015 at 10:45
  • 3
    @Costas, -printf is GNU-only. The OP's mentioning OS/X (a BSD system). Jan 23, 2015 at 11:07
  • 1
    @StéphaneChazelas Thanks. I didn't know such limitation for OS/X (BSD). Poor poor mac' users!
    – Costas
    Jan 23, 2015 at 11:11

2 Answers 2

33

With GNU find:

find . -name foo.mp4 -printf '%h\n'

With other finds, 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.

5
  • When you apply find . , as dirname you will have . instead of entire path. Jan 23, 2015 at 10:47
  • Now how would I translate that to this? find ./ -name "featured.mp4" -exec ffmpeg -i "{}" -c:v libvpx -b:v 1M -c:a libvorbis [NEED DIRECTORY HERE] featured.webm \; I'm using the second suggestion you mentioned.
    – dubbelj
    Jan 23, 2015 at 10:52
  • @MohsenPahlevanzadeh, the OP didn't ask for an absolute path, but for the dirname of the the path. Jan 23, 2015 at 11:05
  • @StéphaneChazelas Sorry for vote down. Jan 23, 2015 at 12:21
  • Thanks @StéphaneChazelas. You helped me make an ffmpeg queue/batch
    – dubbelj
    Jan 23, 2015 at 12:24
0

Below command can also be used to fetch just the directory details.

find ./ -name "foo.mp4" | rev | cut -d"/" -f2- | rev
2
  • 1
    It seems a bit excessive to call three external utilities just to trim a string.
    – Kusalananda
    Nov 9, 2018 at 10:19
  • What's wrong with just using find with -exec dirname {} \; as suggested above for BSD like systems ?
    – Cbhihe
    Dec 11, 2021 at 16:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .