如何在 Bash 中按排序顺序循环所有文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7992689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to loop all files in sorted order in Bash?
提问by Perlnika
I am looping all files in directory with following command:
我正在使用以下命令循环目录中的所有文件:
for i in *.fas; do some_code; done;
However, I get order like this:
但是,我得到这样的订单:
vvchr1.fas
vvchr10.fas
vvchr11.fas
Instead of vvchr1.fas, vvchr2.fas, vvchr3.fas, what is numerical order.
而不是vvchr1.fas、vvchr2.fas、vvchr3.fas,什么是数字顺序。
I have tried sort command, but with no success.
我试过 sort 命令,但没有成功。
回答by catalin.costache
for i in `ls *.fas | sort -V`; do some_code; done;
where sort -V
does according to man sort
a version sort - a natural sort of (version) numbers within text
sort -V
根据man sort
版本排序在哪里做- 文本中的(版本)数字的自然排序
The same using only ls
:
同样只使用ls
:
for i in `ls -v *.fas`; do echo $i; done;
回答by Kusalananda
You will get the files in ASCII order. This means that vvchr10*
comes before vvchr2*
. I realise that you can not rename your files (my bioinformatician brain tells me they contain chromosome data, and we simply don't call chromosome 1 "chr01"), so here's another solution (not using sort -V
which I can't find on any operating system I'm using):
您将按 ASCII 顺序获取文件。这意味着vvchr10*
在vvchr2*
. 我意识到你不能重命名你的文件(我的生物信息学家的大脑告诉我它们包含染色体数据,我们根本不称染色体 1“chr01”),所以这是另一个解决方案(不使用sort -V
我在任何操作上都找不到的解决方案我正在使用的系统):
ls *.fas | sed 's/^\([^0-9]*\)\([0-9]*\)/ /' | sort -k2,2n | tr -d ' ' |
while read filename; do
# do work with $filename
done
This is a bit convoluted and will not work with filenames containing spaces.
这有点令人费解,并且不适用于包含空格的文件名。
Another solution: Suppose we'd like to iterate over the files in size-order instead, which might be more appropriate for some bioinformatics tasks:
另一种解决方案:假设我们想按大小顺序迭代文件,这可能更适合某些生物信息学任务:
du *.fas | sort -k2,2n |
while read filesize filename; do
# do work with $filename
done
To reverse the sorting, just add r
after -k2,2n
(to get -k2,2nr
).
要反转排序,只需r
在-k2,2n
(to get -k2,2nr
)之后添加。
回答by gtangil
With option sort -git compares according to general numerical value
使用选项sort -g它根据一般数值进行比较
for FILE in `ls ./raw/ | sort -g`; do echo "$FILE"; done
0.log 1.log 2.log ... 10.log 11.log
0.log 1.log 2.log ... 10.log 11.log
This will only work if the name of the files are numerical. If they are string you will get them in alphabetical order. E.g.:
这仅在文件名是数字时才有效。如果它们是字符串,您将按字母顺序获得它们。例如:
for FILE in `ls ./raw/* | sort -g`; do echo "$FILE"; done
raw/0.log raw/10.log raw/11.log ... raw/2.log
raw/0.log raw/10.log raw/11.log ... raw/2.log
回答by sorpigal
while IFS= read -r file ; do
ls -l "$file" # or whatever
done < <(find . -name '*.fas' 2>/dev/null | sed -r -e 's/([0-9]+)/ /' | sort -k 2 -n | sed -e 's/ //;'
Solves the problem, presuming the file naming stays consistent, doesn't rely on very-recent versions of GNU sort
, does not rely on reading the output of ls
and doesn't fall victim to the pipe-to-while problems.
解决了这个问题,假设文件命名保持一致,不依赖于最新版本的 GNU sort
,不依赖于读取输出,ls
也不会成为管道到同时问题的受害者。
回答by Some programmer dude
You mean that files with the number 10 comes before files with number 3 in your list? Thats because ls
sorts its result very simple, so something-10.whatever
is smallerthan something-3.whatever
.
您的意思是编号为 10 的文件排在列表中编号为 3 的文件之前?那是因为ls
排序它的结果很简单,所以something-10.whatever
是小比something-3.whatever
。
One solution is to rename all files so they have the same number of digits (the files with single-digit in them start with 0
in the number).
一种解决方案是重命名所有文件,使它们具有相同的位数(其中具有一位数的文件以数字开头0
)。
回答by potong
Like @Kusalananda's solution (perhaps easier to remember?) but catering for all files(?):
就像@Kusalananda 的解决方案一样(也许更容易记住?)但适合所有文件(?):
array=("$(ls |sed 's/[^0-9]*\([0-9]*\)\..*/ &/'| sort -n | sed 's/^[^ ]* //')")
for x in "${array[@]}";do echo "$x";done
In essence add a sort key, sort, remove sort key.
实质上是添加一个排序键,排序,删除排序键。
EDIT: moved comment to appropriate solution
编辑:将评论移至适当的解决方案
回答by David Okwii
use sort -rh and the while loop
使用 sort -rh 和 while 循环
du -sh * | sort -rh | grep -P "avi$" |awk '{print }' | while read f; do fp=`pwd`/$f; echo $fp; done;