私は次のコマンドでディレクトリ内のすべてのファイルをループしています:
for i in *.fas; do some_code; done;
しかし、私はこのような順序を取得します:
vvchr1.fas
vvchr10.fas
vvchr11.fas
vvchr1.fas、vvchr2.fas、vvchr3.fasの代わりに、数値の順序は何ですか。
Sortコマンドを試しましたが、成功しませんでした。
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;
ファイルを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
並べ替えを逆にするには、-k2,2n
の後にr
を追加します(-k2,2nr
を取得します)。
オプションsort -gを使用すると、一般的な数値に従って比較されます
for FILE in `ls ./raw/ | sort -g`; do echo "$FILE"; done
0.log 1.log 2.log ... 10.log 11.log
これは、ファイルの名前が数値の場合にのみ機能します。文字列の場合、アルファベット順に取得します。例えば。:
for FILE in `ls ./raw/* | sort -g`; do echo "$FILE"; done
raw/0.log raw/10.log raw/11.log ... raw/2.log
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
そして、pipe-to-while問題の犠牲になりません。
リストの番号10のファイルが番号3のファイルの前に来るということですか? ls
は結果を非常に単純にソートするため、something-10.whatever
はsomething-3.whatever
よりも小さいです。
1つの解決策は、すべてのファイルの名前を変更して同じ桁数になるようにすることです(数字が1桁のファイルは、数字の0
で始まります)。
@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;