web-dev-qa-db-ja.com

BASH:ソートされた順序ですべてのファイルをループする方法

私は次のコマンドでディレクトリ内のすべてのファイルをループしています:

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

しかし、私はこのような順序を取得します:

vvchr1.fas
vvchr10.fas
vvchr11.fas

vvchr1.fas、vvchr2.fas、vvchr3.fasの代わりに、数値の順序は何ですか。

Sortコマンドを試しましたが、成功しませんでした。

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

ここで、sort -Vman sortバージョンソート-テキスト内の自然な(バージョン)番号のソート

lsのみを使用した同じ:

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

ファイルを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を取得します)。

4
Kusalananda

オプション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

3
gtangil
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問題の犠牲になりません。

1
Sorpigal

リストの番号10のファイルが番号3のファイルの前に来るということですか? lsは結果を非常に単純にソートするため、something-10.whateversomething-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

本質的に、ソートキーを追加し、ソートし、ソートキーを削除します。

編集:コメントを適切なソリューションに移動

0
potong

sort -rhおよびwhileループを使用します

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