问题场景描述
在Linux系统开发中,我们经常需要查找特定类型的文件并按某种规则排序。比如以下命令:
find . ! -path "./build*" -name "*.txt"
会输出类似这样的结果:
./tool/001-sub.txt
./tool/000-main.txt
./zo/001-int.txt
./zo/id/002-and.txt
./as/002-mod.txt
常规排序的问题
如果直接使用sort -n
排序,会得到:
./as/002-mod.txt
./tool/000-main.txt
./tool/001-sub.txt
./zo/001-int.txt
./zo/id/002-and.txt
但实际需求是:
./tool/000-main.txt
./zo/001-int.txt
./tool/001-sub.txt
./zo/id/002-and.txt
./as/002-mod.txt
解决方案
要实现按纯文件名排序但保留完整路径,可以使用以下命令组合:
find . ! -path "./build*" -name "*.txt" -print0 | \
while IFS= read -r -d '' file; do \
printf "%s\\t%s\\n" "$(basename "$file")" "$file"; \
done | \
sort -n | \
cut -f2-
多级子目录处理
对于更复杂的多级子目录结构,上述方法同样适用。例如:
find . -type f -name "*.log" -print0 | \
while IFS= read -r -d '' file; do \
printf "%s\\t%s\\n" "$(basename "$file")" "$file"; \
done | \
sort -k1,1V | \
cut -f2-
性能优化版本
对于大量文件处理,可以使用更高效的awk实现:
find . -type f -name "*.txt" -printf "%f\\t%p\\n" | \
sort -k1,1V | \
cut -f2-
实际应用示例
假设我们需要处理一个项目中的源代码文件:
find src/ -name "*.java" -printf "%f\\t%p\\n" | \
sort -k1,1V | \
cut -f2- | \
xargs javac