对文件名列表进行排序,使子目录中的文件列在父目录中的文件之前

对文件名列表进行排序,使子目录中的文件列在父目录中的文件之前

我有一个包含文件列表的文本文件,例如:

file
A1/file
A1/B1/file
A2/file

如何对其进行排序,以便子目录中的文件列在父目录中的其他文件之前?

A1/B1/file
A1/file
A2/file
file

答案1

这里有一个简单的方法:

awk 'BEGIN{FS="/"; OFS="\t"}{print NF, $0}' file | sort -rn | cut -f2-

A1/B1/file
A2/file
A1/file
file

应该适用于简单的情况,比如你的问题。

如果您还想按目录排序:

awk 'BEGIN{FS="/"; OFS="\t"}{print NF, $0}' file | sort -k1,1rn -k2 | cut -f2-

A1/B1/file
A1/file
A2/file
file

答案2

zsh具有rder glob 扩展epth-first 的odglob 限定符,od

$ print -rC1 -- **/file(Nod)
A2/file
A1/B1/file
A1/file
file

如果使用限定符将文件列表加载到 glob 扩展中,则可以将其应用于任意文件列表e

$ print -rC1 -- /(Ne['reply=( ${(f)"$(<your-file)"} )']od)
A2/file
A1/B1/file
A1/file
file

还按名称排序on

$ print -rC1 -- /(Ne['reply=( ${(f)"$(<your-file)"} )']odon)
A1/B1/file
A1/file
A2/file
file

答案3

为了扩展@Kusalananda的见解,如果这些文件名确实是现有目录树的完整内容,find则可以执行您想要的操作:

鉴于:

$ find .
./f2
./A1
./A1/B1
./A1/B1/f2
./A1/B1/f1
./A1/f2
./A1/f1
./A2
./A2/B1
./A2/B1/C1
./A2/B1/C1/f2
./A2/B1/C1/f1
./A2/f2
./A2/f1
./f1

GNUfind可以:

$ find . -depth -type d -exec find {} -maxdepth 1 -not -type d \;
./A1/B1/f2
./A1/B1/f1
./A1/f2
./A1/f1
./A2/B1/C1/f2
./A2/B1/C1/f1
./A2/f2
./A2/f1
./f2
./f1

如果您关心目录中文件的排序,GNU find 会让您失望,因为它无法控制排序。你可能需要做类似的事情:

$ find . -depth -type d -exec sh -c 'find {} -maxdepth 1 -not -type d | sort' \;
./A1/B1/f1
./A1/B1/f2
./A1/f1
./A1/f2
./A2/B1/C1/f1
./A2/B1/C1/f2
./A2/f1
./A2/f2
./f1
./f2

FreeBSD 和 NetBSD 上的实用find程序将识别-s按文件名排序的标志:

$ find . -depth -type d -exec find -s {} -maxdepth 1 -not -type d \; 
./A1/B1/f1
./A1/B1/f2
./A1/f1
./A1/f2
./A2/B1/C1/f1
./A2/B1/C1/f2
./A2/f1
./A2/f2
./f1
./f2

正如 @StéphaneChazelas 在评论中指出的那样,该-s标志在 OpenBSD 中不可用。即使它可用,find -s也可能会根据您的区域设置等而崩溃,如手册页所述:

注意:“find -s”和“find |” sort' 可能会给出不同的结果。

相关内容