ワイルドカードとスペースを使用したファイル名のリスト

ワイルドカードとスペースを使用したファイル名のリスト

次の例に示すように、変数で指定されたファイルを一覧表示できる必要があります。

X="myfile.txt"
$ ls ${X}

残念ながら、一部の人はファイル名にスペースを使用しているため、次のような場合があります。

X="my file.txt"

次の方法で解決できますls "${X}"

ただし、次のような場合でもこれが発生する可能性があります。

X="my file.*"

ワイルドカードは二重引用符内で拡張されないため、問題が発生します。

すべての状況に適用されるものはありますか?

編集する

X次の配列で宣言されます。

X=("my file."*)
ls "$X[@]"

宣言するとワイルドカード文字が拡張されるため、十分ではありません。使用時に拡張する必要がありますls

答え1

強く打つ

では、bash変数を引用解除することを分割+グローブ演算子と呼ぶこともあります。

分割部分は$IFS特殊パラメータを使用して調整でき、グローバル部分はnoglob次のオプションを使用して調整できます。

ワイルドカードの場合のみ$IFS空の文字列に設定します。

file_pattern='foo bar *.txt'
IFS= # disable splitting
set +o noglob # make sure glob is enabled
ls -ld -- $file_pattern # split+glog with split disabled.

パターンがどのファイルとも一致しない場合は、lsリテラル引数を受け取り、foo bar *.txtファイルが存在しないと文句を言います。

分割に対してのみ($PATHここではコロンで区切られた変数分割が例として使用されます)noglobオプションを設定します。

IFS=: # split on :
set -o noglob
ls -ld -- $PATH # split+glob with glob disabled

空であるか設定されていない場合$var、空であっても拡張時に引数は生成されず、空の引数が生成されます$IFS

$PATH$PATH空(unsetではない)$PATHは、コマンドが現在の作業ディレクトリから取得され、ls引数が渡されないときに現在の作業ディレクトリも一覧表示されることを意味するため、ここでは許可されます。

$PATH現在の作業ディレクトリを意味する(たとえば)に空の要素がある場合、それについて不平を言う対応する空の引数が渡さ/bin::/usr/binれます。ls1つの例外は、空の要素が最後の要素である場合(と同様/bin:/usr/bin:)、最後の要素が削除されることです。

同様の変数を分割するより正しい方法は、次のものを$PATH使用することです。

IFS=:
set -o noglob
printf '<%s>\n' $PATH''

この追加部分は、次の''空の要素が除去されるのを防ぎ、空の要素が$PATHまったく要素ではなく空の要素に分割されることを保証します。

扱いにくい

zshでは、引数の拡張中に分割とワイルドカードは暗黙的に実行されません。$=var-$IFS分割、${(s[separator])var}区切り文字ベースの分割、$~varワイルドカード(または-分割とワイルドカードの$=~var組み合わせ)$IFSを使用して明示的に要求する必要があります。

だから:

file_pattern='foo bar *.txt'
ls -ld -- $~file_pattern

(パターンがどのファイルとも一致しない場合、コマンドはls中断されます²)。

IFS=:
ls -ld -- $=PATH # preserves all empty elements even trailing ones
ls -ld -- ${(s[:])PATH}    # split, discarding empty elements
ls -ld -- "${(@s[:])PATH}" # split, preserving empty elements

¹このオプションを有効にしない限り(管理対象以外のオプションセットではfailglob)bashは中断されます(サブシェルを終了するか、サブシェルで実行されていない場合は読み取ったすべてのコードをスキップします)。または、このオプションを有効にすると、次に展開されます。この場合は何もないため、現在の作業ディレクトリが一覧表示されます。shoptsetnullglob shoptls

²zshで失敗したglobは構文エラーのように処理され、対応するシェルプロセスはエラーと失敗した終了状態で終了します(対話型シェルではデフォルトのシェルを終了せずにプロンプ​​トに戻ります)。ここでは、外部コマンドと同様に、lsこれを実行するために生成されたサブプロセスのみが終了します。グローバル拡張がここで発生するためです。lsたとえば、シェル関数で再定義すると、状況が異なります。

答え2

ワイルドカードを使用したい場合は、変数を使用することは複数のファイルと一致する可能性があるため、良い考えではありません。

解決策:配列を使用してください!

X=("my file."*)
ls "${X[@]}"

# or

for f in "${X[@]}"; do
   some_command "$f"
done

値を割り当てるときは、引用符の*外にする必要があります。

確認するここ変数拡張時のみグローバル拡張のためのソリューションです。

関連情報