*シェルのGlobファイルを使用しない*

*シェルのGlobファイルを使用しない*

特定のサブディレクトリのファイルを一覧表示したいが、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スクリプトの解釈などの簡単な作業を実行するのには余りにも肥大していたため、bashGNUシェルの使用を中止しました。shsh

あなたの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以上を使用するとprintfNLfind文字で区切って出力します。NLとその両方がSPCファイル名に完全に有効な文字であるため、後処理中にこれらの出力を信頼できません。ユーザーに表示するのには適していませんが、後処理には使用できるものを'%s\0'代わりに使用できます'%s\n'(またはサポートされている場合は使用できますfind)。-print0

効率性の観点から、Ubuntu 20.04 /bin/sh(ダッシュ0.5.10.2)とUbuntu 20.04 find(GNU find4.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は、システム、実装、対応するユーティリティのバージョン、およびリンクされたライブラリによって異なります。

今歴史上、全体的な状況この名前は、実際にはglob1970年代初頭に最初の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

おすすめ記事