Bashアスタリスク*ワイルドカードは常に(昇順)ソートされたリストを生成しますか?

Bashアスタリスク*ワイルドカードは常に(昇順)ソートされたリストを生成しますか?

同じ名前のファイルでいっぱいのディレクトリがあります。logXXここで、XXはゼロで埋められた大文字の16進数です。たとえば、次のようになります。

log00
log01
log02
...
log0A
log0B
log0C
...
log4E
log4F
log50
...

通常、ファイルの総数は20〜30個未満です。私の特定のシステム(信頼できるNTPまたはGPSタイムソースを持たない組み込みシステム)では、日付と時刻を信頼できません。ただし、ファイル名は上記のように安定して増加します。

特定の種類の最新の単一ログエントリに対してすべてのファイルを繰り返したいと思います。たとえば、これらのファイルを一緒に配置したいとgrep思います。cat

cat /tmp/logs/log* | grep 'WARNING 07 -' | tail -n1

bashしかし、他のバージョンや異なるshバージョンは、拡張zsh方法について*異なるアイデアを持つことができると思います。

このman bashページでは、拡張子が一致*するファイル名の明示的な昇順アルファベットのリストであるかどうかはわかりません。利用可能なすべてのシステムで試すたびに増加するようです。しかし、定義された動作ですか、それとも実装によって異なりますか?

つまり、cat /tmp/logs/log*すべてのログファイルをアルファベット順にリンクすることに絶対に依存できますか?

ベストアンサー1

すべてのシェルでは、globはデフォルトでソートされます。彼らはすでに/etc/globアシスタントと一緒にいます1970年代初頭、Unixの最初のバージョンでは、glob(したがってglobという名前)を拡張するためにKen Thompsonのシェルによって呼び出されました。

POSIXでは、forなどのユーザーロケールのソート順を使用してshソートする必要がありますが、一部はまだバイト値のみでソートされます。strcoll()lsstrcmp()

$ dash -c 'echo *'
Log01B log-0D log00 log01 log02 log0A log0B log0C log4E log4F log50 log① log② lóg01
$ bash -c 'echo *'
log① log② log00 log01 lóg01 Log01B log02 log0A log0B log0C log-0D log4E log4F log50
$ zsh -c 'echo *'
log① log② log00 log01 lóg01 Log01B log02 log0A log0B log0C log-0D log4E log4F log50
$ ls
log②  log①  log00  log01  lóg01  Log01B  log02  log0A  log0B  log0C  log-0D  log4E  log4F  log50
$ ls | sort
log②
log①
log00
log01
lóg01
Log01B
log02
log0A
log0B
log0C
log-0D
log4E
log4F
log50

ロケールに基づいてソートされたシェルの場合、en_GB.UTF-8ロケールを持つGNUシステムでは-。もっと期待される方法で並べ替えó(少なくとも英国人の場合)、大文字と小文字を無視します(関係決定が関係しない限り)。

しかし、ログ①とログ②の間に若干の不一致があることがわかります。これは、①と②のソート順がGNUロケールで定義されていないためです(まだ、いつかは修正される予定です)。順番が同じなのでランダムな結果が出ます。

ロケールを変更すると、ソート順に影響します。strcmp()同様のソートを得るには、ロケールをCに設定できます。

$ bash -c 'echo *'
log① log② log00 log01 lóg01 Log01B log02 log0.2 log0A log0B log0C log-0D log4E log4F log50
$ bash -c 'LC_ALL=C; echo *'
Log01B log-0D log0.2 log00 log01 log02 log0A log0B log0C log4E log4F log50 log① log② lóg01

一部のロケールでは、完全なASCII文字列全体を使用しても、少し混乱する可能性があります。チェコch語と同様に(少なくともGNUシステムでは)要素の構成ソート後h:

$ LC_ALL=cs_CZ.UTF-8 bash -c 'echo *'
log0Ah log0Bh log0Dh log0Ch

または@ninjaljが指摘したように、ハンガリーのロケールの見知らぬ人もいます。

$ LC_ALL=hu_HU.UTF-8 bash -c 'echo *'
logX LOGx LOGX logZ LOGz LOGZ logY LOGY LOGy

からzshソートを選択できますグローバル予選。たとえば、

echo *(om) # to sort by modification time
echo *(oL) # to sort by size
echo *(On) # for a *reverse* sort by name
echo *(o+myfunction) # sort using a user-defined function
echo *(N)  # to NOT sort
echo *(n)  # sort by name, but numerically, and so on.

echo *(n)次のオプションを使用して数値ソートをグローバルに有効にすることもできますnumericglobsort

$ zsh -c 'echo *'
log① log② log00 log01 lóg01 Log01B log02 log0.2 log0A log0B log0C log-0D log4E log4F log50
$ zsh -o numericglobsort -c 'echo *'
log① log② log00 lóg01 Log01B log0.2 log0A log0B log0C log01 log02 log-0D log4E log4F log50

あなた(私のように)が特定の状況で注文について混乱している場合(ここで私のイギリスのロケールを使用して)、以下を参照してください。ここもっと学ぶ。

おすすめ記事