Il est important de réaliser que c'est en fait le shell qui étend foo*la liste des noms de fichiers correspondants, de sorte que rien ne mvpourrait se faire.
Le problème ici est que, lorsqu'un glob ne correspond pas, certains shell ressemblent bash(et la plupart des autres shell Bourne-like, ce comportement buggy a été introduit par le shell Bourne à la fin des années 70) et transmet le motif à la commande.
Donc ici, quand foo*ne correspond à aucun fichier, au lieu d'abandonner la commande (comme le font les shells pre-Bourne et plusieurs shells modernes), le shell passe un foo*fichier in extenso à mv, demandant donc mvde déplacer le fichier appelé foo*.
Ce fichier n'existe pas. Si c'était le cas, il aurait correspondu au modèle, mvsignale donc une erreur. Si le motif avait été à la foo[xy]place, vous mvauriez pu déplacer accidentellement un fichier appelé à la foo[xy]place des fichiers fooxet fooy.
Maintenant, même dans les obus qui n'ont pas ce problème (pré-Bourne, csh, tcsh, poisson, zsh, bash -O failglob), vous obtiendrez toujours une erreur mv foo* ~/bar, mais cette fois par l'obus.
Si vous voulez considérer que ce n'est pas une erreur s'il n'y a pas de correspondance de fichier foo*et dans ce cas, ne déplacez rien, vous voudriez créer d'abord la liste des fichiers (d'une manière qui ne provoque pas d'erreur, comme en utilisant l' nullgloboption de certains shells), et alors seulement appeler si mvla liste est non vide.
Ce serait mieux que de cacher toutes les erreurs de mv(comme l'ajoutant 2> /dev/null) comme si cela mvéchouait pour une autre raison, vous voudriez probablement encore savoir pourquoi.
en zsh
files=(foo*(N)) # where the N glob qualifier activates nullglob for that glob
(($#files == 0)) || mv -- $files ~/bar/
Ou utilisez une fonction anonyme pour éviter d'utiliser une variable temporaire:
() { (($# == 0)) || mv -- "$@" ~/bar/; } foo*(N)
zshest un de ces shells qui n’a pas le bogue Bourne et rapporte une erreur sans exécuter la commande quand un glob ne correspond pas (et que l’ nullgloboption n’a pas été activée), alors ici, vous pouvez masquer zshl’erreur et restaurer stderr pendant mvsi vous voyez toujours les mverreurs s'il y en a, mais pas l'erreur concernant les globs non correspondants:
(mv 2>&3 foo* ~/bar/) 3>&2 2>&-
Ou vous pourriez utiliser zargsce qui éviterait également les problèmes si le foo*glob devenait trop volumineux.
autoload zargs # best in ~/.zshrc
zargs -r -- foo* -- mv -t ~/bar # here assuming GNU mv for its -t option
En ksh93:
files=(~(N)foo*)
((${#files[#]} == 0)) || mv -- "${files[@]}" ~/bar/
En bash:
bashn'a pas de syntaxe à activer nullglobpour un seul glob, et l' failgloboption est annulée nullglob, vous aurez donc besoin d'éléments comme:
saved=$(shopt -p nullglob failglob) || true
shopt -s nullglob
shopt -u failglob
files=(foo*)
((${#files[@]} == 0)) || mv -- "${files[@]}" ~/bar/
eval "$saved"
ou définissez les options dans un sous-shell pour enregistrer devez les enregistrer avant et les restaurer ensuite.
(
shopt -s nullglob
shopt -u failglob
files=(foo*)
((${#files[@]} == 0)) || mv -- "${files[@]}" ~/bar/
)
Dans yash
(
set -o nullglob
files=(foo*)
[ "${#files[@]}" -eq 0 ] || mv -- "${files[@]}" ~/bar/
)
Dans fish
Dans la coquille de poisson, le comportement nullglob est le comportement par défaut de la setcommande, il s'agit donc simplement de:
set files foo*
count $files > /dev/null; and mv -- $files ~/bar/
POSIXly
Il n'y a aucune nullgloboption dans POSIX shet aucun tableau autre que les paramètres de position. Il existe une astuce que vous pouvez utiliser pour détecter si un glob correspond ou non:
set -- foo[*] foo*
if [ "$1$2" != 'foo[*]foo*' ]; then
shift
mv -- "$@" ~/bar/
fi
En utilisant a foo[*]et foo*glob, nous pouvons différencier le cas où il n'y a pas de fichier correspondant à celui où il y a un fichier appelé foo*(ce qui set -- foo*n'a pas pu être fait).
Plus de lecture:
mv foo* ~/bar/ 2> /dev/null?