Answers:
在GNU中,find
您可以-printf
为此使用参数,例如:
find /dir1 -type f -printf "%f\n"
-o
,优先级比隐含的低-a
,因此您经常希望对您的-o
论点进行分组)
如果发现没有-printf选项,则还可以使用basename:
find ./dir1 -type f -exec basename {} \;
... {} ';'
使用-execdir
会自动将当前文件保存在中{}
,例如:
find . -type f -execdir echo '{}' ';'
您也可以使用$PWD
代替.
(在某些系统上,它不会在前面产生额外的点)。
如果仍然有多余的点,则可以运行:
find . -type f -execdir basename '{}' ';'
-execdir utility [argument ...] ;
的
-execdir
初级是相同的-exec
初级不同之处在于实用程序将来自该目录被执行保持当前文件。
如果使用+
代替;
,则{}
每次实用程序调用都将被替换为尽可能多的路径名。换句话说,它将在一行中打印所有文件名。
./filename
代替filename
。根据您的需要,它可能会或可能不会很好。
$PWD
代替.
。
如果您使用的是GNU,请查找
find . -type f -printf "%f\n"
或者您可以使用诸如Ruby(1.9+)之类的编程语言
$ ruby -e 'Dir["**/*"].each{|x| puts File.basename(x)}'
如果您喜欢bash(至少4个)解决方案
shopt -s globstar
for file in **; do echo ${file##*/}; done
如果只想对文件名运行某些操作,则使用起来basename
可能很困难。
例如:
find ~/clang+llvm-3.3/bin/ -type f -exec echo basename {} \;
只会回显basename /my/found/path
。如果要对文件名执行,则不是我们想要的。
但是您可以xargs
输出。例如,根据另一个目录中的名称杀死目录中的文件:
cd dirIwantToRMin;
find ~/clang+llvm-3.3/bin/ -type f -exec basename {} \; | xargs rm
find ~/clang+llvm-3.3/bin/ -type f -exec basename {} \;
-exec
而且-execdir
很慢,xargs
是国王。
$ alias f='time find /Applications -name "*.app" -type d -maxdepth 5'; \
f -exec basename {} \; | wc -l; \
f -execdir echo {} \; | wc -l; \
f -print0 | xargs -0 -n1 basename | wc -l; \
f -print0 | xargs -0 -n1 -P 8 basename | wc -l; \
f -print0 | xargs -0 basename | wc -l
139
0m01.17s real 0m00.20s user 0m00.93s system
139
0m01.16s real 0m00.20s user 0m00.92s system
139
0m01.05s real 0m00.17s user 0m00.85s system
139
0m00.93s real 0m00.17s user 0m00.85s system
139
0m00.88s real 0m00.12s user 0m00.75s system
xargs
的并行性也有帮助。
有趣的是,我无法解释没有的最后一种xargs
情况-n1
。它给出正确的结果,并且是最快的¯\_(ツ)_/¯
(basename
仅接受1个路径参数,但xargs
不带-n1
。将全部发送(实际上为5000个)。不适用于linux和openbsd,仅适用于macOS ...)
可以从linux系统中获得一些更大的数据,以了解如何提供-execdir
帮助,但比并行处理要慢得多xargs
:
$ alias f='time find /usr/ -maxdepth 5 -type d'
$ f -exec basename {} \; | wc -l; \
f -execdir echo {} \; | wc -l; \
f -print0 | xargs -0 -n1 basename | wc -l; \
f -print0 | xargs -0 -n1 -P 8 basename | wc -l
2358
3.63s real 0.10s user 0.41s system
2358
1.53s real 0.05s user 0.31s system
2358
1.30s real 0.03s user 0.21s system
2358
0.41s real 0.03s user 0.25s system
find
它是-execdir
最快的,因为创建新进程是相对昂贵的操作。
正如其他人指出的那样,您可以合并find
和basename
,但是默认情况下该basename
程序一次只能在一个路径上运行,因此该可执行文件必须为每个路径启动一次(使用find ... -exec
或find ... | xargs -n 1
),这可能会很慢。
如果在上使用-a
选项basename
,则它可以在一次调用中接受多个文件名,这意味着您可以xargs
不使用-n 1
来将路径分组为更少的调用数量basename
,这应该更有效率。
例:
find /dir1 -type f -print0 | xargs -0 basename -a
在这里,我包括了-print0
and -0
(应该一起使用),以便处理文件和目录名称中的任何空格。
这是xargs basename -a
和xargs -n1 basename
版本之间的时间比较。(为了进行类似比较,此处报告的时序是在初始虚拟运行之后执行的,因此它们都在文件元数据已复制到I / O缓存之后才完成。)cksum
在这两种情况下,只是为了证明输出与所使用的方法无关。
$ time sh -c 'find /usr/lib -type f -print0 | xargs -0 basename -a | cksum'
2532163462 546663
real 0m0.063s
user 0m0.058s
sys 0m0.040s
$ time sh -c 'find /usr/lib -type f -print0 | xargs -0 -n 1 basename | cksum'
2532163462 546663
real 0m14.504s
user 0m12.474s
sys 0m3.109s
如您所见,避免basename
每次启动实际上确实要快得多。
basename
可以接受多个文件名,而无需任何其他命令行参数。-a
在Linux上使用here。(basename --version
告诉我basename (GNU coreutils) 8.28
。)
我找到了一个解决方案(在makandracards页面上),该解决方案仅提供最新的文件名:
ls -1tr * | tail -1
(感谢Arne Hartherz)
我用它cp
:
cp $(ls -1tr * | tail -1) /tmp/