BASH:如何按排序顺序循环所有文件

时间:2011-11-03 09:35:09

标签: bash sorting loops

我使用以下命令循环目录中的所有文件:

for i in *.fas; do some_code; done;

但是,我得到这样的命令:

vvchr1.fas
vvchr10.fas
vvchr11.fas

而不是vvchr1.fas,vvchr2.fas,vvchr3.fas,什么是数字顺序。

我尝试过sort命令,但没有成功。

7 个答案:

答案 0 :(得分:82)

for i in `ls *.fas | sort -V`; do some_code; done;

其中sort -V根据man sort版本排序 - 文本中的一种自然类型(版本)数字

仅使用ls

for i in `ls -v *.fas`; do echo $i; done;

答案 1 :(得分:4)

您将按ASCII顺序获取文件。这意味着vvchr10*出现在vvchr2*之前。我意识到你不能重命名你的文件(我的生物信息学大脑告诉我它们包含染色体数据,我们根本就不称为染色体1“chr01”),所以这是另一个解决方案(不使用sort -V我可以'找到我正在使用的任何操作系统):

ls *.fas | sed 's/^\([^0-9]*\)\([0-9]*\)/\1 \2/' | sort -k2,2n | tr -d ' ' |
while read filename; do
  # do work with $filename
done

这有点令人费解,不适用于包含空格的文件名。

另一种解决方案:假设我们希望以大小顺序迭代文件,这可能更适合某些生物信息学任务:

du *.fas | sort -k2,2n |
while read filesize filename; do
  # do work with $filename
done

要反转排序,只需在r之后添加-k2,2n(以获取-k2,2nr)。

答案 2 :(得分:3)

使用选项 sort -g ,它会根据一般数值

进行比较
 for FILE in `ls ./raw/ | sort -g`; do echo "$FILE"; done

0.log 1.登录 2.登录 ... 10.log 11.log

这仅在文件名为数字时才有效。如果它们是字符串,您将按字母顺序获取它们。 E.g:

 for FILE in `ls ./raw/* | sort -g`; do echo "$FILE"; done

生/ 0.log 生/ 10.log 生/ 11.log ... 生/ 2.登录

答案 3 :(得分:1)

您的意思是编号为10的文件位于列表中编号为3的文件之前?多数民众赞成因为ls对结果的排序非常简单,因此something-10.whatever 小于而不是something-3.whatever

一种解决方案是重命名所有文件,使其具有相同的位数(其中包含单个数字的文件以数字中的0开头)。

答案 4 :(得分:1)

while IFS= read -r  file ; do
    ls -l "$file" # or whatever
done < <(find . -name '*.fas' 2>/dev/null | sed -r -e 's/([0-9]+)/ \1/' | sort -k 2 -n | sed -e 's/ //;'

解决问题,假设文件命名保持一致,不依赖于最新版本的GNU sort,不依赖于读取ls的输出并且不会成为受害者对于管道问题。

答案 5 :(得分:0)

喜欢@ Kusalananda的解决方案(也许更容易记住?)但是要适应所有文件(?):

array=("$(ls |sed 's/[^0-9]*\([0-9]*\)\..*/\1 &/'| sort -n | sed 's/^[^ ]* //')")
for x in "${array[@]}";do echo "$x";done

实质上添加排序键,排序,删除排序键。

编辑:将评论移至适当的解决方案

答案 6 :(得分:0)

使用sort -rh和while循环

du -sh * | sort -rh | grep -P "avi$" |awk '{print $2}' | while read f; do fp=`pwd`/$f; echo $fp; done;