非対話型スクリプトでは、zsh拡張は異なる動作をしますか?

非対話型スクリプトでは、zsh拡張は異なる動作をしますか?

私は現在非常に単純なzshスクリプトを書いています。私が通常することは次のとおりです。

mv */*.{a,b} .

zshスクリプトで実行すると、サイズが異なるように調整され、インタラクティブモードで作業すると失敗します。

% mkdir dir
% touch dir/file.a
% ls file.a
ls: cannot access file.a: No such file or directory
% mv */*.{a,b} .
% ls file.a
file.a

したがって、これはうまくいきますが、スクリプトでは次のようになります。

% mkdir dir
% touch dir/file.a
% ls file.a
ls: cannot access file.a: No such file or directory
% cat script.sh
#!/usr/bin/zsh
mv */*.{a,b} .
% ./script.sh
./script.sh:2: no matches found: */*.b

では、違いは何ですか?私は何が間違っていましたか?

ベストアンサー1

両方のデフォルトオプション設定が正しくありませんzsh。代わりにasコマンドを使用すると、echo何が起こっているのかを簡単に確認できますmv

null_globインタラクティブにオプションを設定したようです。zshドキュメントによると、このオプションはデフォルトでは設定されていません。このオプションをオフにするとどうなりますか?nomatch他のオプションが設定されているかどうかによって異なります。nomatchunset( ) を使用すると、nonomatch次のような結果が得られます。

% mkdir dir
% touch dir/file.a
% ls file.a
ls: cannot access file.a: No such file or directory
% echo */*.{a,b} .
dir/file.a */*.b .

拡張は2つの段階で行われます。まず、*/*.{a,b}2 単語に拡張します。*/*.aand */*.b。その後、各単語はグローバルパターンに展開されます。最初のものdir/file.aは一致するものがないため、2番目のものは独自に拡張され、2番目のものは独自に拡張されます。これが意味するのは、mvand not を使用する場合は、echo2 つのファイル (音) と (該当ファイルなし) をmv移動しなければならないということです。これは、などのほとんどのシェルでデフォルトで発生します。dir/file.a*/*.bshksgbash

zsh デフォルトオプションの設定はnull_glob設定されずにnomatch設定されます。スクリプトはデフォルトのオプション設定で実行されます(実際に~/.zshenv変更しないでください、または変更/etc/zshenvしない限り)。これはスクリプトから次のことを意味します。

% mkdir dir
% touch dir/file.a
% ls file.a
ls: cannot access file.a: No such file or directory
% cat script.sh
#!/usr/bin/zsh
echo */*.{a,b} .
% ./script.sh
./script.sh:2: no matches found: */*.b

一致するものがないため、*/*.bエラーが発生しますnomatch

/ commandの前にスクリプトを挿入すると、上記のsetopt nonomatch誤った動作に戻ります。存在しないファイルを移動しようとします。echomv

/コマンドの前にスクリプトを挿入すると、setopt null_glob有効なインタラクティブシェルから得られる動作が得られます。echomv

おすすめ記事