foo*
一致するファイル名のリストにそれを展開するのは実際にはシェルであるため、mv
それ自体で実行できることはほとんどないことを認識することが重要です。
ここでの問題は、globが一致しない場合、一部のシェルbash
(および他のほとんどのBourneのようなシェル、70年代後半にBourneシェルによって実際に導入されたバグ)がパターンに逐語的にコマンドを渡すことです。
ときだからここに、foo*
代わりにコマンドを中止する任意のファイルを、(前のBourneシェルおよびいくつかの近代的なシェルが行うように)一致していない、シェルはそのまま渡しfoo*
にファイルをmv
ので、基本的に求めて、mv
という名前のファイルを移動することfoo*
。
そのファイルは存在しません。一致した場合、実際にパターンに一致したはずなのでmv
、エラーを報告します。パターンがfoo[xy]
代わりにあった場合、とファイルの代わりにmv
呼び出されたファイルを誤って移動していた可能性があります。foo[xy]
foox
fooy
さて、その問題のないシェル(Bourne、csh、tcsh、fish、zsh、bash -O failglob)でも、エラーが発生しますmv foo* ~/bar
が、今回はシェルによってエラーが発生します。
一致するファイルがない場合はエラーではなく、foo*
その場合は何も移動しないと見なしたい場合は、最初にファイルのリストを作成します(nullglob
オプションを使用するなどのエラーを引き起こさない方法で)いくつかのシェル)、そして唯一の呼び出しmv
はリストが空でないことです。
他の理由で失敗したかのように(追加するように)すべてのエラーを非表示にするよりも、おそらく理由を知りたいと思うでしょう。mv
2> /dev/null
mv
zshで
files=(foo*(N)) # where the N glob qualifier activates nullglob for that glob
(($#files == 0)) || mv -- $files ~/bar/
または、匿名関数を使用して、一時変数の使用を避けます。
() { (($# == 0)) || mv -- "$@" ~/bar/; } foo*(N)
zsh
Bourneバグがないシェルの1つであり、globが一致しない場合(およびnullglob
オプションが有効になっていない場合)にコマンドを実行せずにエラーを報告するため、ここで、zsh
エラーを非表示にして復元できますstderrの場合mv
、mv
エラーがあれば表示されますが、一致しないグロブに関するエラーは表示されません。
(mv 2>&3 foo* ~/bar/) 3>&2 2>&-
またはzargs
、foo*
globがあまりにもmanファイルに展開される場合に、これを使用して問題を回避することもできます。
autoload zargs # best in ~/.zshrc
zargs -r -- foo* -- mv -t ~/bar # here assuming GNU mv for its -t option
ksh93の場合:
files=(~(N)foo*)
((${#files[#]} == 0)) || mv -- "${files[@]}" ~/bar/
bashの場合:
bash
nullglob
1つのglobのみを有効にする構文はありません。failglob
オプションはキャンセルされるnullglob
ため、次のようなものが必要になります。
saved=$(shopt -p nullglob failglob) || true
shopt -s nullglob
shopt -u failglob
files=(foo*)
((${#files[@]} == 0)) || mv -- "${files[@]}" ~/bar/
eval "$saved"
または、サブシェルでオプションを設定して保存する必要があり、それらを前に保存し、後で復元する必要があります。
(
shopt -s nullglob
shopt -u failglob
files=(foo*)
((${#files[@]} == 0)) || mv -- "${files[@]}" ~/bar/
)
に yash
(
set -o nullglob
files=(foo*)
[ "${#files[@]}" -eq 0 ] || mv -- "${files[@]}" ~/bar/
)
に fish
フィッシュシェルでは、nullglobの動作がset
コマンドのデフォルトであるため、次のようになります。
set files foo*
count $files > /dev/null; and mv -- $files ~/bar/
POSIXly
nullglob
POSIXにはオプションがsh
なく、定位置パラメーター以外の配列はありません。ただし、グロブが一致したかどうかを検出するために使用できるトリックがあります。
set -- foo[*] foo*
if [ "$1$2" != 'foo[*]foo*' ]; then
shift
mv -- "$@" ~/bar/
fi
a foo[*]
とfoo*
globの両方を使用することにより、一致するファイルがない場合と、たまたま呼び出されるfoo*
(set -- foo*
できなかった)ファイルが1つある場合を区別できます。
もっと読む:
mv foo* ~/bar/ 2> /dev/null
?