如何在文件名最大的每个目录中查找文件?

时间:2012-06-22 14:14:57

标签: linux bash

我有一个看起来像这样的文件结构

./501.res/1.bin
./503.res/1.bin
./503.res/2.bin
./504.res/1.bin

我希望找到每个目录中.bin文件的文件路径,该文件的编号最高。所以我要找的输出是

./501.res/1.bin
./503.res/2.bin
./504.res/1.bin

文件的最高编号为9。

问题

我如何在BASH中做到这一点?

我已经到了find .|grep bin|sort

6 个答案:

答案 0 :(得分:3)

保证全球按词汇顺序扩展。

for dir in ./*/
do
    files=($dir/*)           # create an array
    echo "${files[@]: -1}"   # access its last member
done

答案 1 :(得分:2)

测试:

find . -type d -name '*.res' | while read dir; do
    find "$dir" -maxdepth 1 | sort -n | tail -n 1
done

答案 2 :(得分:1)

使用awk怎么样?你可以非常简单地获得第一次:

[ghoti@pc ~]$ cat data1
./501.res/1.bin
./503.res/1.bin
./503.res/2.bin
./504.res/1.bin
[ghoti@pc ~]$ awk 'BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1' data1
./501.res/1.bin
./503.res/1.bin
./504.res/1.bin
[ghoti@pc ~]$ 

要获得最后一次出现,您可以管理几种类型:

[ghoti@pc ~]$ sort -r data1 | awk 'BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1' | sort
./501.res/1.bin
./503.res/2.bin
./504.res/1.bin
[ghoti@pc ~]$ 

鉴于你正在使用“find”和“grep”,你可能会这样做:

find . -name \*.bin -type f -print | sort -r | awk 'BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1' | sort

这是如何运作的?

find命令有许多有用的选项,包括通过glob选择文件,选择文件类型等的能力。它已经知道的输出,它成为sort -r的输入

首先,我们以反向(sort -r)对输入数据进行排序。这可以确保在任何目录中,编号最大的文件将首先显示。这个结果被输入awk。 FS是字段分隔符,它使$2成为“/ 501”,“/ 502”等内容.Awk脚本具有condition {action}形式的部分,可以对每行输入进行评估。如果缺少某个条件,则该操作将在每一行上运行。如果条件为“1”并且没有动作,则打印该行。所以这个脚本分解如下:

  • a[$2] {next} - 如果存在下标$ 2(即“/ 501”)的数组a,则跳转到下一行。否则...
  • {a[$2]=1} - 将数组的下标$ 2设置为1,以便将来第一个条件评估为true,然后......
  • 1 - 打印线。

此awk脚本的输出将是您想要的数据,但顺序相反。最后的sort会按照您期望的顺序重新开始。

现在......这是很多管道,当你要求它同时处理数百万行输入时,排序可能会有点资源浪费。这个解决方案对于少量文件来说是完全足够的,但是如果你正在处理大量的输入,请告诉我们,我可以提出一个多功能的awk解决方案(需要超过60秒)写)。

<强>更新

Per Dennis的圣训建议,我上面包含的awk脚本可以通过改变

来改进
BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1

BEGIN{FS="."} $2 in a {next} {a[$2]} 1

虽然这在功能上是相同的,但优点是您只需定义数组成员而不是为它们赋值,这可能会节省内存或CPU,具体取决于您的awk实现。无论如何,它更清洁。

答案 3 :(得分:0)

我想出了类似的东西:

for dir in $(find . -mindepth 1 -type d | sort); do
   file=$(ls "$dir" | sort | tail -n 1);
   [ -n "$file" ] && (echo "$dir/$file");
done

也许它可以更简单

答案 4 :(得分:0)

如果从find中调用shell是一个选项,请尝试使用

  find * -type d -exec sh -c "echo -n './'; ls -1 {}/*.bin | sort -n -r | head -n 1" \;

答案 5 :(得分:0)

这是一个班轮

find . -mindepth 1 -type d | sort | sed -e "s/.*/ls & | sort | tail -n 1 | xargs -I{} echo &\/{}/" | bash