GNU/Linux >> Linux の 問題 >  >> Linux

Bash Star *ワイルドカードは常に(昇順の)ソート済みリストを生成しますか?

logXXのような名前のファイルでいっぱいのディレクトリがあります ここで、XXは、次のような2文字のゼロが埋め込まれた大文字の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*に頼ることができますか すべてのログファイルをアルファベット順に連結するには?

承認された回答:

すべてのシェルで、グロブはデフォルトでソートされます。それらはすでに/etc/globによるものでした 70年代初頭のUnixの最初のバージョンでグロブを拡張するためにケントンプソンのシェルによって呼び出されたヘルパー(そしてグロブに名前を付けました)。

shの場合 、POSIXでは、strcoll()を使用してソートする必要があります。 、つまり、lsのように、ユーザーのロケールで並べ替え順序を使用しています strcmp()を介して実行するものもありますが 、これはバイト値のみに基づいています。

$ 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システムであることに気付くかもしれません。 ロケール、- ファイル名のソートでは無視されます(ほとんどの句読文字は無視されます)。 ó (少なくとも英国の人々にとっては)より期待される方法でソートされ、ケースは無視されます(関係を決定する場合を除く)。

ただし、log①log②にはいくつかの矛盾があります。これは、①と②の並べ替え順序がGNUロケールで定義されていないためです(現在、いつか修正されることを願っています)。それらは同じようにソートされるため、ランダムな結果が得られます。

関連:子孫を処理しますか?

ロケールを変更すると、並べ替え順序に影響します。ロケールをCに設定して、strcmp()を取得できます。 -並べ替えのように:

$ 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のすべてのalnum文字列でも混乱が生じる可能性があることに注意してください。 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で 、glob修飾子を使用した並べ替えを選択できます。例:

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

あなたが(私がそうであったように)その特定のインスタンスでその順序に混乱している場合(ここでは私の英国のロケールを使用しています)、詳細についてはここを参照してください。


Linux
  1. Bashの「評価」コマンド?

  2. 〜常に$ homeと等しいですか?

  3. Bash翻訳ファイルにすべてのエラーテキストが含まれていないのはなぜですか?

  1. Bashスクリプトでは、Continueコマンドは埋め込みループでどのように機能しますか?

  2. Bashの正規表現が変数であり、直接ではない場合にのみ機能するのはなぜですか?

  3. 「bash -c」は何をしますか?

  1. root アカウントの UID/GID は常に 0 ですか?

  2. bash でアスタリスク (*) 文字をエスケープする

  3. -e は bash シバンで何をしますか?