我使用查找目录中的所有文件,所以我得到了一个路径列表。但是,我只需要文件名。例如,我得到。/dir1/dir2/file.txt,我想要得到file.txt
如果您正在使用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
我已经找到了一个解决方案(在makandracards页面),这给了最新的文件名:
ls -1tr * | tail -1
(感谢Arne Hartherz)
我用它来写cp:
cp $(ls -1tr * | tail -1) /tmp/
如果您只想对文件名运行一些操作,那么使用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
使用-execdir自动保存当前文件{},例如:
find . -type f -execdir echo '{}' ';'
您也可以使用$PWD代替。(在某些系统上,它不会在前面产生一个额外的点)。
如果你仍然有一个额外的点,或者你可以运行:
find . -type f -execdir basename '{}' ';'
-execdir utility[参数…]]; -execdir primary与-exec primary相同,不同之处在于实用程序将从包含当前文件的目录执行。
当使用+而不是;时,对于每次实用程序调用,{}将被替换为尽可能多的路径名。换句话说,它将在一行中打印所有文件名。
-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会发送所有的路径参数(实际上是5000个)而不带-n1。不适用于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
老实说,basename和dirname解决方案更简单,但你也可以看看这个:
find . -type f | grep -oP "[^/]*$"
or
find . -type f | rev | cut -d '/' -f1 | rev
or
find . -type f | sed "s/.*\///"
正如其他人指出的那样,您可以将find和basename结合起来,但是默认情况下basename程序一次只在一个路径上操作,因此可执行文件必须为每个路径启动一次(使用find…-exec或find…| xargs -n 1),可能会很慢。
如果您在basename上使用-a选项,那么它可以在一次调用中接受多个文件名,这意味着您可以使用xargs而不使用-n 1,将路径组合在一起,形成更少的basename调用,这应该更有效。
例子:
find /dir1 -type f -print0 | xargs -0 basename -a
这里我包含了-print0和-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实际上要快得多。
推荐文章
- Shell脚本删除超过n天的目录
- 使用sudo时未找到命令
- 当有命令行参数时,如何使用GDB分析程序的核心转储文件?
- 如何检查shell脚本中是否存在命令?
- 如何使用查找命令从列表中查找所有具有扩展名的文件?
- 如何强制从另一个SSH会话分离屏幕?
- 如何打破一个循环在Bash?
- 如何将文件指针(file * fp)转换为文件描述符(int fd)?
- Linux Bash中双&和分号有什么区别?
- 如何合并2 JSON对象从2个文件使用jq?
- 在SSH会话中查找客户端的IP地址
- C++ Linux的想法?
- 如何为Fedora安装g++ ?
- Linux删除大小为0的文件
- Spring引导应用程序作为服务