How to sort the results of find (including nested directories) alphabetically in bash

后端 未结 3 1798
心在旅途
心在旅途 2021-02-04 12:58

I have a list of directories based on the results of running the \"find\" command in bash. As an example, the result of find are the files:

test/a/file
test/b/fi         


        
3条回答
  •  暖寄归人
    2021-02-04 13:45

    If you have the GNU version of find, try this:

    find test -type f -printf '%h\0%d\0%p\n' | sort -t '\0' -n | awk -F '\0' '{print $3}'
    

    To use these file names in a loop, do

    find test -type f -printf '%h\0%d\0%p\n' | sort -t '\0' -n | awk -F '\0' '{print $3}' | while read file; do
        # use $file
    done
    

    The find command prints three things for each file: (1) its directory, (2) its depth in the directory tree, and (3) its full name. By including the depth in the output we can use sort -n to sort test/file above test/a/file. Finally we use awk to strip out the first two columns since they were only used for sorting.

    Using \0 as a separator between the three fields allows us to handle file names with spaces and tabs in them (but not newlines, unfortunately).

    $ find test -type f
    test/b/file
    test/a/file
    test/file
    test/z/file
    $ find test -type f -printf '%h\0%d\0%p\n' | sort -t '\0' -n | awk -F'\0' '{print $3}'
    test/file
    test/a/file
    test/b/file
    test/z/file
    

    If you are unable to modify the find command, then try this convoluted replacement:

    find test -type f | while read file; do
        printf '%s\0%s\0%s\n' "${file%/*}" "$(tr -dc / <<< "$file")" "$file"
    done | sort -t '\0' | awk -F'\0' '{print $3}'
    

    It does the same thing, with ${file%/*} being used to get a file's directory name and the tr command being used to count the number of slashes, which is equivalent to a file's "depth".

    (I sure hope there's an easier answer out there. What you're asking doesn't seem that hard, but I am blanking on a simple solution.)

提交回复
热议问题