kshまたはzshとは異なり、bashには、配列または任意の文字列のリストをソートするための組み込みサポートがありません。それはグロブかの出力をソートすることができaliasたりsetまたはtypeset(これらの最後の3は、ユーザーのロケールのソート順序ではないが)、それは事実上、ここで使用することはできません。
文字列の任意のリストを簡単に並べ替えることができるPOSIXツールチェストには何もありません¹(sort行を並べ替えるので、NULおよび改行以外の短い文字列(LINE_MAXは多くの場合PATH_MAXより短い)だけですが、ファイルパスは他の空でないバイトシーケンスです) 0より)。
あなたがあなた自身のソートアルゴリズムを実装することができるようにしながら、awk(使用して<文字列比較演算子を)かさえbash(使用[[ < ]]中の任意のパスのために、) bash、移植性、最も簡単にはに頼るかもしれperl。
を使用するとbash4.4+、次のことができます。
readarray -td '' sorted_filearray < <(perl -MFile::Basename -l0 -e '
print for sort {basename($a) cmp basename($b)} @ARGV' -- "${filearray[@]}")
これは-のstrcmp()ような順序になります。グロブやの出力のように、ロケールの照合規則に基づく順序の場合ls、に-Mlocale引数を追加しますperl。数値ソート(GNUのようなより多くの場合sort -g、それは次のように数字をサポートして+3、1.2e-5そしてない千セパレータ、ではないがhexadimals)、使用<=>の代わりに、cmp(そして再び-Mlocaleのためのように表彰されるユーザの小数点以下のマークのためのsortコマンド)。
コマンドの引数の最大サイズによって制限されます。これを回避するには、perl引数を使用する代わりに、ファイルのリストを標準入力に渡すことができます。
readarray -td '' sorted_filearray < <(
printf '%s\0' "${filearray[@]}" | perl -MFile::Basename -0le '
chomp(@files = <STDIN>);
print for sort {basename($a) cmp basename($b)} @files')
の古いバージョンではbash、while IFS= read -rd ''代わりにループを使用するreadarray -d ''かperl、適切に引用されたパスのリストを出力して、それをに渡すことができましたeval "array=($(perl...))"。
を使用zshすると、並べ替え順序を定義できるグロブ拡張を偽造できます。
sorted_filearray=(/(e{'reply=($filearray)'}oe{'REPLY=$REPLY:t'}))
ではreply=($filearray)、私たちは実際には(最初はちょうどだったグロブ展開を強制/配列の要素であることを)。次に、ファイル名の末尾に基づいてソート順を定義します。
strcmp()様オーダー、(GNUに似た数値ソートのためにCにロケール修正sort -Vではなく、sort -n比較する際の重要な違いは1.4と1.23ロケールで(.例えば)小数マークである)を、追加nグロブ修飾子を。
の代わりにoe{expression}、関数を使用して次のような並べ替え順序を定義することもできます。
by_tail() REPLY=$REPLY:t
またはより高度なもの:
by_numbers_in_tail() REPLY=${(j:,:)${(s:,:)${REPLY:t}//[^0-9]/,}}
(したがってa/foo2bar3.pdf(2,3の数値)はb/bar1foo3.pdf(1,3)の後、c/baz2zzz10.pdf(2,10)の前にソートされます)、次のように使用します。
sorted_filearray=(/(e{'reply=($filearray)'}no+by_numbers_in_tail))
もちろん、本来の目的である本当のグロブに適用できます。たとえば、pdfbasename / tailでソートされた、任意のディレクトリ内のファイルのリストの場合:
pdfs=(**/*.pdf(N.oe+by_tail))
a strcmp()ベースの並べ替えが受け入れ可能で、短い文字列の場合は、文字列を16進エンコーディングに変換してから、ソートawkに渡してsortから変換し直すことができます。