如何只用linux`get`获取文件名?

时间:2011-03-28 07:58:57

标签: linux shell find

我正在使用find目录中的所有文件,因此我得到了一个路径列表。但是,我只需要文件名。即我得到./dir1/dir2/file.txt,我想获得file.txt

10 个答案:

答案 0 :(得分:298)

在GNU find中,您可以使用-printf参数,例如:

find /dir1 -type f -printf "%f\n"

答案 1 :(得分:139)

如果您的find没有-printf选项,您也可以使用basename:

find ./dir1 -type f -exec basename {} \;

答案 2 :(得分:22)

使用-execdir自动保存{}中的当前文件,例如:

find . -type f -execdir echo '{}' ';'

您也可以使用$PWD代替.(在某些系统中,它不会在前面产生额外的点)。

如果你还有一个额外的点,或者你可以运行:

find . -type f -execdir basename '{}' ';'
  

-execdir utility [argument ...] ;

     

-execdir主要内容与-exec主要内容相同,但实用程序将从保存当前文件的目录执行。

使用+而不是;时,{}将替换为每次调用实用程序时尽可能多的路径名。换句话说,它会在一行中打印所有文件名。

答案 3 :(得分:21)

如果您正在使用GNU find

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

答案 4 :(得分:11)

如果您只想对文件名运行某些操作,则使用basename可能会很困难。

例如:

find ~/clang+llvm-3.3/bin/ -type f -exec echo basename {} \; 

只会回显基本名称/my/found/path。如果我们想在文件名上执行,那不是我们想要的。

但是你可以xargs输出。例如,根据另一个目录中的名称杀死目录中的文件:

cd dirIwantToRMin;
find ~/clang+llvm-3.3/bin/ -type f -exec basename {} \; | xargs rm

答案 5 :(得分:5)

在Mac(BSD find)上使用:

find /dir1 -type f -exec basename {} \;

答案 6 :(得分:2)

正如其他人指出的那样,您可以组合使用findbasename,但是默认情况下basename程序一次只能在一个路径上运行,因此可执行文件必须为每个路径启动一次(使用find ... -execfind ... | xargs -n 1),这可能很慢。

如果您在-a上使用basename选项,那么它可以在一次调用中接受多个文件名,这意味着您可以在不使用xargs的情况下使用-n 1 ,以将路径归为更少的basename调用,这应该更有效率。

示例:

find /dir1 -type f -print0 | xargs -0 basename -a

在这里,我包括了-print0-0(应该一起使用),以便处理文件和目录名称中的任何空格。

这是xargs basename -axargs -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确实要快得多。

答案 7 :(得分:1)

-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 ...)< / p>

从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

答案 8 :(得分:1)

老实说,basenamedirname解决方案更容易,但是您也可以查看以下内容:

find . -type f | grep -oP "[^/]*$"

find . -type f | rev | cut -d '/' -f1 | rev

find . -type f | sed "s/.*\///"

答案 9 :(得分:-3)

我找到了一个解决方案(在makandracards页面上),它只提供了最新的文件名:

ls -1tr * | tail -1

(感谢Arne Hartherz)

我将它用于cp

cp $(ls -1tr * | tail -1) /tmp/