排序-如何在Bash中按排序顺序循环播放所有文件?
我正在使用以下命令循环目录中的所有文件:
for i in *.fas; do some_code; done;
但是,我得到这样的订单:
vvchr1.fas
vvchr10.fas
vvchr11.fas
用数字顺序代替vvchr1.fas,vvchr2.fas,vvchr3.fas。
我尝试了排序命令,但没有成功。
for i in `ls *.fas | sort -V`; do some_code; done;
其中ls
根据man sort
做版本排序-文本中自然的(版本)数字排序
同样只使用ls
:
for i in `ls -v *.fas`; do echo $i; done;
您将以ASCII顺序获取文件。 这意味着r
早于-k2,2n
。我意识到您无法重命名文件(我的生物信息学家的大脑告诉我它们包含染色体数据,而我们根本不将1号染色体称为“ chr01”),因此这是另一种解决方案(不使用-k2,2nr
我在使用的任何操作系统上都找不到):
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
要反转排序,只需在-k2,2n
之后添加r
(以获得-k2,2nr
)。
使用选项sort -g时,它将根据常规数值进行比较
for FILE in `ls ./raw/ | sort -g`; do echo "$FILE"; done
0.log1.日志2.日志...10.日志11.日志
仅当文件名是数字时,这才起作用。 如果它们是字符串,则将按字母顺序获取它们。 例如。:
for FILE in `ls ./raw/* | sort -g`; do echo "$FILE"; done
raw / 0.lograw / 10.lograw / 11.log...raw / 2.log
您是说列表中编号为10的文件位于编号3之前? 那是因为0
非常简单地对其结果进行排序,因此something-10.whatever
小于something-3.whatever
。
一种解决方案是重命名所有文件,使它们具有相同的数字位数(其中具有一位数字的文件以0
开头)。
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
的输出,并且不会成为管道到同时问题的受害者。
就像@Kusalananda的解决方案(也许更容易记住吗?),但可以满足所有文件的需要(?):
array=("$(ls |sed 's/[^0-9]*\([0-9]*\)\..*/\1 &/'| sort -n | sed 's/^[^ ]* //')")
for x in "${array[@]}";do echo "$x";done
从本质上说,添加排序键,排序,删除排序键。
编辑:将评论移至适当的解决方案
使用sort -rh和while循环
du -sh * | sort -rh | grep -P "avi$" |awk '{print $2}' | while read f; do fp=`pwd`/$f; echo $fp; done;