Une commande telle que mv foo* ~/bar/
produit ce message dans stderr si aucun fichier ne correspond foo*
.
mv: cannot stat `foo*': No such file or directory
Cependant, dans le scénario sur lequel je travaille, tout irait bien, et j'aimerais supprimer ce message de nos journaux.
Y a-t-il un bon moyen de dire mv
de rester silencieux même si rien n'a été déplacé?
mv foo* ~/bar/ 2> /dev/null
?mv
. :) Mais ça ira, bien sûr.mv
implémentations prennent en charge une-q
option pour les calmer, mais cela ne fait pas partie de la spécification POSIX pourmv
. Lesmv
coreutils in GNU, par exemple, n’ont pas cette option.Réponses:
Vous cherchez cela?
la source
set -e
(qui doit être utilisé dans chaque script shell) échouera. vous pouvez ajouter un|| true
pour désactiver la vérification pour une seule commande.set -e
ne doit pas être utilisé dans tous les scripts shell, car dans de nombreux cas, la gestion des erreurs est encore plus complexe qu’elle ne l’est.En fait, je ne pense pas que la mise en sourdine
mv
soit une bonne approche (rappelez-vous que cela pourrait aussi vous rapporter d'autres choses qui pourraient être intéressantes ... par exemple manquantes~/bar
). Vous souhaitez le désactiver uniquement si votre expression globale ne renvoie pas de résultats. En fait plutôt ne pas l'exécuter du tout.Ne semble pas très attrayant, et ne fonctionne que dans
bash
.OU
sauf que vous êtes
bash
avecnullglob
ensemble. Vous payez un prix de 3 fois la répétition du motif glob.la source
foo*
lorsqu'il est le seul du répertoire en cours qui correspond au globfoo*
. Cela peut être contourné avec une expression globale qui ne correspond pas à elle-même, difficile. Par exemple[ 'fo[o]*' = "$(echo fo[o]*)" ] || mv fo[o]* ~/bar/
.find . -maxdepth 1 -name 'foo*' -type f -print0 | xargs -0r mv -t ~/bar/
- GNU
mv
a une belle option "destination en premier" (-t
) etxargs
peut ignorer l'exécution de sa commande s'il n'y a aucune entrée (-r
). L' utilisation de-print0
et-0
fait en conséquence assurer qu'il n'y aurait pas un gâchis lorsque les noms de fichiers contiennent des espaces et d' autres choses « drôle ».la source
-maxdepth
,-print0
,-0
et-r
sont également des extensions GNU (bien que certains d'entre eux se trouvent dans d' autres implémentations de nos jours).mv
.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 nemv
pourrait 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 unfoo*
fichier in extenso àmv
, demandant doncmv
de déplacer le fichier appeléfoo*
.Ce fichier n'existe pas. Si c'était le cas, il aurait correspondu au modèle,
mv
signale donc une erreur. Si le motif avait été à lafoo[xy]
place, vousmv
auriez pu déplacer accidentellement un fichier appelé à lafoo[xy]
place des fichiersfoox
etfooy
.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'nullglob
option de certains shells), et alors seulement appeler simv
la liste est non vide.Ce serait mieux que de cacher toutes les erreurs de
mv
(comme l'ajoutant2> /dev/null
) comme si celamv
échouait pour une autre raison, vous voudriez probablement encore savoir pourquoi.en zsh
Ou utilisez une fonction anonyme pour éviter d'utiliser une variable temporaire:
zsh
est 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’nullglob
option n’a pas été activée), alors ici, vous pouvez masquerzsh
l’erreur et restaurer stderr pendantmv
si vous voyez toujours lesmv
erreurs s'il y en a, mais pas l'erreur concernant les globs non correspondants:Ou vous pourriez utiliser
zargs
ce qui éviterait également les problèmes si lefoo*
glob devenait trop volumineux.En ksh93:
En bash:
bash
n'a pas de syntaxe à activernullglob
pour un seul glob, et l'failglob
option est annuléenullglob
, vous aurez donc besoin d'éléments comme:ou définissez les options dans un sous-shell pour enregistrer devez les enregistrer avant et les restaurer ensuite.
Dans
yash
Dans
fish
Dans la coquille de poisson, le comportement nullglob est le comportement par défaut de la
set
commande, il s'agit donc simplement de:POSIXly
Il n'y a aucune
nullglob
option dans POSIXsh
et 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:En utilisant a
foo[*]
etfoo*
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 quiset -- foo*
n'a pas pu être fait).Plus de lecture:
la source
Ce n'est probablement pas le meilleur, mais vous pouvez utiliser la
find
commande pour vérifier si le dossier est vide ou non:la source
foo*
chemin de recherche littéral àfind
.Je suppose que vous utilisez bash, car cette erreur dépend du comportement de bash pour développer des globs sans correspondance entre eux. (En comparaison, zsh génère une erreur lorsqu’on tente de développer un glob sans correspondance.)
Alors, qu'en est-il de la solution de contournement suivante?
Cela ignorera silencieusement le
mv
sils -d foo*
échoue, tout en enregistrant les erreurs sils foo*
réussit maismv
échoue. (Attention,ls foo*
peut échouer pour des raisons autresfoo*
qu'existantes, par exemple des droits insuffisants, un problème lié au service fixe, etc., de sorte que de telles conditions seraient ignorées en silence par cette solution.)la source
bash
). +1 pour prendre en compte le fait que celamv
pourrait échouer pour d'autres raisons quefoo*
non existantes.ls
commande ne serait pas très clair pour les futurs lecteurs, du moins sans commentaire.)ls -d foo*
pourrait retourner avec un statut de sortie non nul pour d'autres raisons également, comme après unln -s /nowhere foobar
(au moins avec certainesls
implémentations).Vous pouvez faire par exemple
mv 1>/dev/null 2>&1 foo* ~/bar/
oumv foo* ~/bar/ 1&>2
Pour plus de détails, voir: http://mywiki.wooledge.org/BashFAQ/055
la source
mv foo* ~/bar/ 1&>2
ne fait pas taire la commande, il envoie ce qui aurait été sur stdout pour être également sur stderr./dev/null
parNUL
1
et2
veulent dire?Vous pouvez tricher (portable) avec
perl
:la source
Si vous utilisez Perl, vous pouvez aussi bien aller jusqu'au bout:
ou comme one-liner:
(Pour plus de détails sur la
move
commande, consultez la documentation de File :: Copy .)la source
Au lieu
tu peux faire
Simple, lisible :)
la source
cp
nerm
se taisent sifoo*
n'existe pas.Si la commande précédente est réussie ou non, nous pouvons trouver le statut de sortie de la commande précédente
si sortie de echo $? est différent de 0 signifie que la commande est non fructueuse si la sortie est 0, cela signifie que la commande est réussie
la source