How to only get file name with Linux 'find'?

后端 未结 10 1333
故里飘歌
故里飘歌 2020-11-28 18:19

I\'m using find to all files in directory, so I get a list of paths. However, I need only file names. i.e. I get ./dir1/dir2/file.txt and I want to get fi

相关标签:
10条回答
  • 2020-11-28 18:37

    If you are using GNU find

    find . -type f -printf "%f\n"
    

    Or you can use a programming language such as Ruby(1.9+)

    $ ruby -e 'Dir["**/*"].each{|x| puts File.basename(x)}'
    

    If you fancy a bash (at least 4) solution

    shopt -s globstar
    for file in **; do echo ${file##*/}; done
    
    0 讨论(0)
  • 2020-11-28 18:37

    On mac (BSD find) use:

    find /dir1 -type f -exec basename {} \;
    
    0 讨论(0)
  • 2020-11-28 18:38

    If your find doesn't have a -printf option you can also use basename:

    find ./dir1 -type f -exec basename {} \;
    
    0 讨论(0)
  • 2020-11-28 18:38

    I've found a solution (on makandracards page), that gives just the newest file name:

    ls -1tr * | tail -1
    

    (thanks goes to Arne Hartherz)

    I used it for cp:

    cp $(ls -1tr * | tail -1) /tmp/
    
    0 讨论(0)
  • 2020-11-28 18:40

    In GNU find you can use -printf parameter for that, e.g.:

    find /dir1 -type f -printf "%f\n"
    
    0 讨论(0)
  • 2020-11-28 18:40

    -exec and -execdir are slow, xargs is king.

    $ 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's parallelism also helps.

    Funnily enough i cannot explain the last case of xargs without -n1. It gives the correct result and it's the fastest ¯\_(ツ)_/¯

    (basename takes only 1 path argument but xargs will send them all (actually 5000) without -n1. does not work on linux and openbsd, only macOS...)

    Some bigger numbers from a linux system to see how -execdir helps, but still much slower than a parallel 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
    
    0 讨论(0)
提交回复
热议问题