我有一个看起来像这样的文件结构
./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
答案 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