web-dev-qa-db-ja.com

ワイルドカードを使用して作成され、スペースを含むパスを変数に格納する方法

これが状況です(私はMac、OS X El Capitanを使用しています):

# This works:

$ cd /Applications/Adobe\ Illustrator*/Cool\ Extras.localized/en_US/Templates/;

# These do not work:

$ INSTALL_DIR=/Applications/Adobe\ Illustrator*/Cool\ Extras.localized/en_US/Templates;
$ cd $INSTALL_DIR
# Moves me here: /Applications/Adobe

$ cd "$INSTALL_DIR"
-bash: cd: /Applications/Adobe Illustrator*/Cool Extras.localized/en_US/Templates: No such file or directory

$ cd "${INSTALL_DIR}"
-bash: cd: /Applications/Adobe Illustrator*/Cool Extras.localized/en_US/Templates: No such file or directory

私の目標は、tar$INSTALL_DIRを次のように使用することです。

$ tar -xz $SOURCE_Zip --strip-components 1 -C $INSTALL_DIR "*.ait";

残念ながら、-C(宛先ディレクトリに変更)は$INSTALL_DIRのスペースが好きではありません。引用符を使用すると、*が機能しなくなります。

このシナリオを処理するエレガントな方法はありますか?

5
mhulse

*が引用されていない場合、シェルはコマンドを実行する前に引数リストを展開します。それは展開引数リストをプログラムに渡します。

*が引用符付き文字列に含まれている場合、プログラムに渡される前にシェルによって展開されません。

パスを展開して別の変数に割り当て、次に引数として渡すときに2番目の変数を引用してみてください。

2
Chad Clark

問題はtarではなく、シェルコードにあります。 -Cオプションの引数は、ワイルドカードパターンではなくパスであることが想定されています。 cdコマンドでまったく同じ問題が発生したことに注意してください。

INSTALL_DIR変数にワイルドカードパターンを格納しました。 -C $INSTALL_DIRを記述する場合、これは「split + glob」演算子を適用します。変数の値を取り、空白で分割し、各Wordをワイルドカードパターンとして解釈してから、展開します。ここで、変数の値は/Applications/Adobe Illustrator*/Cool Extras.localized/en_US/Templatesで、3つの単語に分割されます/Applications/AdobeIllustrator*/CoolExtras.localized/en_US/Templates;中央のWordにはワイルドカード(*)が含まれているため、ワイルドカードパターンとして解釈されますが、どのファイルにも一致しないため、パターンはそのまま残されます。これにより、-Cオプションの引数が文字列/Applications/Adobeになり、tarコマンドにはIllustrator*/CoolExtras.localized/en_US/Templatesの2つの引数があります。

二重引用符を使用する場合、"$INSTALL_DIR"は変数INSTALL_DIRの値になります。 *がまだ展開されていないため、まだ展開されていません。

経験則として、ワイルドカードは、複数の単語が予想されるコンテキストで展開されます。結局のところ、一般に、ワイルドカードパターンは複数のファイルに一致します。結果は単一の文字列であることが期待されるため、割り当ての右側はワイルドカード展開を抑制します。代わりにリストを取得するには、文字列変数ではなく配列変数に割り当てます。

INSTALL_DIRS=(/Applications/Adobe\ Illustrator*/Cool\ Extras.localized/en_US/Templates)

複数のバージョンのIllustratorがインストールされている場合、複数の配列要素が存在する可能性があります。最後の要素を見てみましょう。

INSTALL_DIR=${INSTALL_DIRS[$((${#INSTALL_DIRS}-1))]}

ここで、INSTALL_DIRは既存のファイルへのパスです(ワイルドカードが一致したと想定)。通常どおり使用できます(つまり、二重引用符で囲むことができます)。

tar -xz "$SOURCE_Zip" --strip-components 1 -C "$INSTALL_DIR" "*.ait"