コマンドの変数拡張がZSHでは機能しませんが、BASHでは機能するのはなぜですか?

コマンドの変数拡張がZSHでは機能しませんが、BASHでは機能するのはなぜですか?

環境変数を設定してコマンドを呼び出すときに使用したいのですが、サイコロはありません。

変数のないコマンド全体が機能します。

nacho@WouldntYouLikeToKnow ~ % ls -la ~/Downloads             
total 8675309
drwx------+ 16 nacho  staff        512 Sep 28 10:30 .
drwxr-x---+ 29 nacho  staff        928 Sep 29 10:39 ..

これで変数を設定して使用しようとしましたが、失敗しました。

nacho@WouldntYouLikeToKnow ~ % export testing="-la ~/Downloads"

nacho@WouldntYouLikeToKnow ~ % ls $testing
ls: invalid option --  
usage: ls [-@ABCFGHILOPRSTUWabcdefghiklmnopqrstuvwxy1%,] [--color=when] [-D format] [file ...]

答え1

複数の個々の文字列(パラメータ)を単一の文字列に埋めることは、少なくともその個々の文字列を再抽出する必要がある場合は、ほとんど常に誤ったアプローチです。

あなたがやっていることはbashシェルで動作します(シェルが二重引用符の中でチルダ拡張を実行しないので、代わりに使用すると仮定します$HOME)。文字列を空白文字に分割するためです(; および Unquoted 変数拡張はファイル名のグロービングの結果の単語)、シェルでは実行しません.~$IFSzsh

bashがないので動作することに注意してください。その他文字列にスペース、タブ、または改行があり、文字列にファイル名のワイルドカードが含まれていません。あなたの方法は間違いなくいいえbashたとえば、パス名にスペースが含まれている場合、または名前付きディレクトリの内容を一覧表示したい場合に使用できます*

両方のシェルの変数に別々のコマンドライン引数を格納する正しい方法は、配列を使用することです。

args=( -la ~/Downloads )

または

args=( -l -A ~/Library/'Application Support' )

bashシェルではこれを次のように使用できます。

ls "${args[@]}"

ここでは、各要素が個別に参照される"${args[@]}"配列要素のリストに展開されます。args

シェルでもzsh同じことを行うか、次のことができます。

ls $args

ここでzsh、シェルは配列をargs別の要素に拡張します。各要素は引数になりますが、ls基本的に要素を分割したり、ファイル名のグロービングを適用したりすることはありません。

また、この例では、チルダを引用符なしでそのままにして、シェルがチルダをユーザーのホームディレクトリのパス名に拡張できるようにします。この拡張は、args値を使用するのではなく、配列に割り当てるときに発生します。

関連:

関連情報