特定のサブディレクトリのファイルを一覧表示したいが、dockerコンテナの一部としてこれを行うので、docker exec
実際には必要ないシェルを実行するのを妨げたくありません。単純なコマンドラインツール(シェルだけでなく)を使用してすべてのglobエントリを見つけることはできますか?
たとえば、現在の呼び出しはです。一般的に使用されているツールを使用して、よりシンプルで軽量なbash -l -c 'echo /usr/local/conda-meta/*.json'
類似のものを作成することは可能ですか?globber /usr/local/conda-meta/*.json
答え1
sh
シンプルで普遍的に利用可能です。sh
さまざまな言語でコマンドラインを解析するために呼び出されるツールですsystem(cmdline)
。一部のGNUオペレーティングシステムを含む多くのオペレーティングシステムは、コマンドラインの解析やPOSIXスクリプトの解釈などの簡単な作業を実行するのには余りにも肥大していたため、bash
GNUシェルの使用を中止しました。sh
sh
あなたのbash -l -c 'echo /usr/local/conda-meta/*.json'
コマンドラインが解釈のために呼び出されたかもしれませんsh
。たぶんこれを行うことができます:
printf '%s\n' /usr/local/conda-meta/*.json
まっすぐ。そうでない場合:
sh -c 'printf "%s\n" /usr/local/conda-meta/*.json'
ここでもfind
使用できます。find
ワイルドカードを使用しませんが、シェルに似たパターンに一致するファイル名を報告できます。
LC_ALL=C find /usr/local/conda-meta/. ! -name . -prune -name '*.json'
またはいくつかのfind
実装を介して:
LC_ALL=C find /usr/local/conda-meta -mindepth 1 -maxdepth 1 -name '*.json'
(シェル構成である現在のロケールで有効な文字を形成するバイトシーケンスだけでなく、すべてのバイトシーケンスがここでLC_ALL=C
一致する必要があります*
。シェルがコマンドラインを解釈しない場合に変更する必要があるかもしれませんenv LC_ALL=C find...
。)
シェルグローブとのいくつかの違い:
- ファイルリストがソートされていません。
- 隠しファイルを含める(追加し
! -name '.*'
て除外できます) - 一致するファイルがない場合、出力は提供されません。グローブには、拡張されていないパターンをそのまま残すバグ機能があります。
- 最初の(標準)バリアントを使用すると、ファイルが
/usr/local/conda-meta/./file.json
。 - 一部のglobは
x*/y/../*z
簡単に翻訳されません(この場合はディレクトリシンボリックリンクの他の動作に注意してください)。
ただし、任意のデータを出力するために使用することはできませんecho
。
私の次の質問は:その出力で何をしますか?を使用すると、echo
ファイルパスをSPC文字で区切って出力し、my以上を使用するとprintf
NLfind
文字で区切って出力します。NL
とその両方がSPC
ファイル名に完全に有効な文字であるため、後処理中にこれらの出力を信頼できません。ユーザーに表示するのには適していませんが、後処理には使用できるものを'%s\0'
代わりに使用できます'%s\n'
(またはサポートされている場合は使用できますfind
)。-print0
効率性の観点から、Ubuntu 20.04 /bin/sh
(ダッシュ0.5.10.2)とUbuntu 20.04 find
(GNU find
4.7.0)を比較してください。
開始時間:
$ time (repeat 1000 sh -c '')
( repeat 1000; do; sh -c ''; done; ) 0.91s user 0.66s system 105% cpu 1.483 total
$ time (repeat 1000 find . -quit)
( repeat 1000; do; find . -quit; done; ) 1.35s user 1.25s system 103% cpu 2.507 total
ワイルドカード 一部のjson
ファイル:
$ TIMEFMT='%U user %S system %P cpu %*E total'
$ time (repeat 1000 sh -c 'printf "%s\n" /usr/share/iso-codes/json/*.json') > /dev/null
0.95s user 0.72s system 105% cpu 1.587 total
$ time (repeat 1000 find /usr/share/iso-codes/json -mindepth 1 -maxdepth 1 -name '*.json') > /dev/null
1.34s user 1.35s system 103% cpu 2.599 total
Evenはここよりもbash
遅いです。find
$ time (repeat 1000 bash -c 'printf "%s\n" /usr/share/iso-codes/json/*.json') > /dev/null
1.53s user 1.36s system 102% cpu 2.808 total
もちろん、YMMVは、システム、実装、対応するユーティリティのバージョン、およびリンクされたライブラリによって異なります。
今歴史上、全体的な状況この名前は、実際にはglob
1970年代初頭に最初のUnixバージョンで呼び出されたユーティリティ名に由来していました。ワイルドカードパターンを拡張するためのヘルパーとして検索され、呼び出さ/etc
れます。sh
非常に古い樹皮を復活させるためのいくつかのプロジェクトをオンラインで見つけることができます。https://etsh.nl/。考古学の練習として、glob
次のことができるユーティリティを構築できます。
glob printf '%s\n' '/usr/local/conda-meta/*.json'
しかし、いくつかの注意事項があります。
[!x]
これはサポートされていない古代球です[^x]
。- 8ビットでは安全ではありません。実際、ビット8は次の目的に使用されます。逃げるglob演算子(で始まるファイル名と一致するものと
$'\xe9*'
同じものと一致します。シェルは呼び出す前に引用符のビット8を設定します)i*
$'\xaa*'
*
glob
- 範囲(例:
[a-f]
照合ではなくバイト値の一致)(実際に私の考えでは、これはしばしば利点です)。 - 一致しない地球はエラーを引き起こす可能性があります
No match
。 (再び言うが、おそらくより良いでしょう。壊れた1970年代後半、Bourneシェルによって開発されました。
glob
その後、1970年代後半にPWBシェルとBourneシェルを始め、この機能がシェルに移されました。後で他のアプリケーションでその機能を使用できるようにするために、一部の機能がfnmatch()
Cglob()
ライブラリに追加されましたが、この機能の基本インターフェイスである標準または一般的なユーティリティは不明です。当初も、perl
グローバルスキーマを拡張するために呼び出すために使用されました。csh