Linux中如何按文件名排序查找子目录文件并保留路径信息


阅读 2 次

问题场景描述

在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