I'm looking to get a list of just file names (without the rest of the path) when executing the find command from a terminal. How do I accomplish this on the mac?
7 Answers
With basename:
find . -type f -exec basename {} \;
- What are curly braces for?nullpotent– nullpotent2013-07-17 12:51:51 +00:00Commented Jul 17, 2013 at 12:51
- basename is run once for every found file, denoted by {}.Ярослав Рахматуллин– Ярослав Рахматуллин2013-07-17 14:02:05 +00:00Commented Jul 17, 2013 at 14:02
- what is the mean of the \ and ; ?neouyghur– neouyghur2016-12-24 10:49:38 +00:00Commented Dec 24, 2016 at 10:49
- @neouyghur
;terminates the-execaction. The\is needed because;also has special meaning to the shell.8bittree– 8bittree2017-09-22 20:49:16 +00:00Commented Sep 22, 2017 at 20:49
Evilsoup mentioned that what was posted doesn't work for spaced file names. So instead you could use:
find . -type f -print0 | while IFS= read -r -d '' filename; do echo ${filename##*/}; done - This will break on files with spaces in their names (see parsing ls on greg's wiki)evilsoup– evilsoup2013-07-16 22:08:28 +00:00Commented Jul 16, 2013 at 22:08
- +1 for speed. I don't know if I did something wrong, but this one took 1 second on my $HOME, whereas all others took around 10 seconds. Of course, I would need more than 10 seconds to look this up and type it.Paulo Almeida– Paulo Almeida2013-07-16 23:19:20 +00:00Commented Jul 16, 2013 at 23:19
With GNU find, you can do:
find ~/tmp/ -printf "%f\n" This is probably worth trying in OS X too.
- 3
-printfisn't supported on OS X's BSDfind.2013-07-16 21:22:56 +00:00Commented Jul 16, 2013 at 21:22 - 1Also,
-printfbears little relation to the Cprintfor the POSIX shell utilityprintf. Using this historic function name for something different is very poorly considered. The conservative BSD guys likely see it the same way, so we won't probably won't see clone of-printfin the BSD find, under that name.Kaz– Kaz2013-07-17 00:42:32 +00:00Commented Jul 17, 2013 at 0:42 - I disagree that it's poorly considered to use a familiar function name to perform a similar task in a different context. Why BSD will probably never support it is another matter.Ярослав Рахматуллин– Ярослав Рахматуллин2013-07-17 14:02:54 +00:00Commented Jul 17, 2013 at 14:02
There is a better way to strip everything but the last portion of a file path; with awk. It is better because awk is not executed once for every file. In some cases this matters.
find ~/tmp/ -type f | awk -F/ '{ print $NF }' We look only for files in ~/tmp and we get a list where every entry is separated by slashes. Hence, we use a slash as the field separator (-F/) and print the field parameter ($1..$9) that corresponds to the last field ($NF).
- This is the fastest I tested.Paulo Almeida– Paulo Almeida2013-07-17 14:25:27 +00:00Commented Jul 17, 2013 at 14:25
- I've been using Cygwin lately, and creating a process in windows is super expensive...Ярослав Рахматуллин– Ярослав Рахматуллин2013-07-17 14:30:35 +00:00Commented Jul 17, 2013 at 14:30
EDIT:
Using sed:
$ find . -type f | sed 's/.*\///' Using the xargs command, as mentioned in the response of @nerdwaller
$ find . -type f -print0 | xargs --null -n1 basename - 1Thanks for pointing that one out, +1, I haven't used xargs much... Definitely should since you dropped quite a few characters off my command.nerdwaller– nerdwaller2013-07-16 20:49:25 +00:00Commented Jul 16, 2013 at 20:49
- This one breaks when files have spaces. It works like this, at least in a quick test:
find . -type f -print0| xargs --null -n1 basenamePaulo Almeida– Paulo Almeida2013-07-17 14:28:53 +00:00Commented Jul 17, 2013 at 14:28 - Neither of
--nullor-n1options is available on OSXValeriy Van– Valeriy Van2018-03-23 16:58:45 +00:00Commented Mar 23, 2018 at 16:58
You can call sh from within find's -exec option and avoid using uneccesary pipes. This also has the advantage that you don't need to worry about funny filenames (spaces, newlines, etc.):
find . -type f -exec sh -c 'echo "${0##*/}"' {} \; What about this:
find … | egrep -o -e '[^/]+$' Advantage: Only exactly one additional process is spawned, not one for each result.