I am looping all files in directory with following command:
for i in *.fas; do some_code; done;
However, I get order like this:
<
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/ //;'
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.
use sort -rh and the while loop
du -sh * | sort -rh | grep -P "avi$" |awk '{print $2}' | while read f; do fp=`pwd`/$f; echo $fp; done;
Like @Kusalananda's solution (perhaps easier to remember?) but catering for all files(?):
array=("$(ls |sed 's/[^0-9]*\([0-9]*\)\..*/\1 &/'| 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
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 smaller than 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).
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):
ls *.fas | sed 's/^\([^0-9]*\)\([0-9]*\)/\1 \2/' | 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
).
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
The same using only ls
:
for i in `ls -v *.fas`; do echo $i; done;