Comment faire en sorte que rm ne crée pas d'erreur si un fichier n'existe pas?

329

J'écris un fichier makefile qui va nettoyer des fichiers inutiles à la fin de la compilation. Si une cible a déjà été créée, elle sera bien sûr ignorée et le fichier inutile pourrait ne pas y figurer. Donc si je fais ça:

rm lexer.ml interpparse.ml interpparse.mli

Je risque d’obtenir des erreurs car l’un des fichiers n’existe pas. Est-il possible de dire rmd'ignorer ces fichiers?

En lisant la page de manuel, je vois l’option suivante:

 -f          Attempt to remove the files without prompting for confirma-
             tion, regardless of the file's permissions.  If the file does
             not exist, do not display a diagnostic message or modify the
             exit status to reflect an error.  The -f option overrides any
             previous -i options.

Cela ressemble presque à ce que je veux, mais je ne suis pas vraiment sûr de la partie autorisations. Y a-t-il un moyen de faire cela?

Jason Baker
la source
En avez-vous essayé rmdans un bac à sable? On dirait -fque vous faites exactement ce que vous voulez, quel que soit le dépassement.
JMD
Si les autorisations ne le permettent pas, rm tentera -ftoujours de le supprimer avec l' option. Ça va échouer. Il ne vous dira pas qu'il a échoué. Utile si le nom de fichier est une variable ou un glob.
LawrenceC
juste pour être complet: il y en a rm --interactive=neverqui agit comme rm -fsauf que ça retourne un état de sortie d'erreur. voir ici pour plus de détails: unix.stackexchange.com/questions/72864/…
lesmana Le

Réponses:

283

L' -foption est définitivement ce que vous voulez utiliser.

La confirmation concernant les autorisations de fichiers auxquelles il fait référence est la suivante:

$ touch myfile    
$ chmod 400 myfile
$ rm myfile       
rm: remove write-protected regular empty file `myfile'?

Alors rmvous avertira si vous essayez de supprimer un fichier que vous ne disposez pas des autorisations d'écriture sur. Ceci est autorisé si vous avez des autorisations d'écriture sur le répertoire mais que vous êtes un peu bizarre, c'est pourquoi rmvous en avertissez normalement.

Dave Webb
la source
1
La plupart des systèmes, mais pas tous, demanderont (je pense). Certains exigent -i.
DaveParillo
1
Si vous voulez le message d'erreur, mais pas le code de sortie d'erreur, voir la réponse de Giel Berkers . J'utilise set -edans tous mes scripts bash pour que le script se ferme après qu'une commande donne une erreur. Je veux souvent qu'un script me dise s'il y rma une erreur, mais continue quand même. continue.
Cledoux
124

Une autre solution est celle-ci: https://stackoverflow.com/questions/11231937/bash-ignoring-error-for-a-particular-command

Ajoutez simplement une instruction OR après votre commande:

rm -rf my/dir || true

De cette façon, lorsque l'instruction n ° 1 échoue (génère une erreur), exécutez l'instruction n ° 2, qui est simplement true.

Giel Berkers
la source
4
Il imprime l'erreur et continue l'exécution, ce qui était souhaité pour mon cas.
worldsayshi
9
Ou juste rm -rf my/dir ||:pour être encore plus concis ( :c'est court true)
Godsmith
La meilleure solution à mon avis. Il est facile de voir ce qui se passe et pourquoi le code de résultat est ignoré. Je l'aime!
Mavamaarten
76

Je suis bien en retard à la fête, mais je l'utilise tout le temps. Dans un fichier make, ajoutez -au début d'une ligne pour ignorer la valeur de retour de cette ligne. Ainsi:

-rm lexer.ml interpparse.ml interpparse.mli
Robert Li
la source
9
Cela restera quand même une erreur sur la console, ce qui vous entraînera à ignorer les erreurs dans la sortie, ce qui n’est probablement pas ce que vous voulez. rm -rf est une meilleure option à mon avis.
Godsmith
@ Godsmith Je préférerais ignorer une erreur que de forcer la suppression récursive. Cela pourrait être très méchant. Et +1 pour la syntaxe spécifique du makefile
Daishi
Si rm -rf peut être "méchant", cela signifie que vous utilisez make en dehors d'un répertoire sous contrôle de version. Pourquoi?
Godsmith
Donnez un lien vers la documentation, s'il vous plaît. Pourrait trouver une description de cette fonctionnalité.
George Sovetov
14

Si vous ne souhaitez pas utiliser l'option -f, une alternative est la suivante:

rm filethatdoesntexist 2> /dev/null 

Cela empêchera simplement les erreurs d'être imprimées.

utilisateur135299
la source
9
Malheureusement, cela donnera toujours un code de sortie d'erreur.
Shaun McDonald
8

Si vous trouvez un moyen de supprimer les noms de fichiers, rmne vous plaindez pas s'il ne trouve pas de correspondance. Donc, quelque chose comme lexer.m* interpparse.*, etc. devrait fonctionner pour vous (faites attention, vous ne supprimez pas trop, bien sûr). En outre, -fc’est un moyen tout à fait raisonnable, tant que vous n’espérez pas que les autorisations de fichiers vous éviteront de supprimer un fichier que vous ne souhaitiez pas - si vous ne souhaitez pas le supprimer, ne le mettez pas de côté. dans la liste.

Nick Bastin
la source
Il serait hors de question de laisser tomber le fichier car il existe un fichier lexer.mll que je ne souhaite pas supprimer. Merci de montrer pourquoi -f est raisonnable. Je suppose que j'ai tendance à être trop prudent après un peu trop d'égarement sudo rm -rf.
Jason Baker
Pas même un plus restrictif lexer.m?...? Cela attraperait lexer.mlet lexer.mz, mais pas lexer.mllou lexer.mla.
JMD
1
@JMD: Je suppose que cela dépend de votre shell et de la prise en charge du filtrage par motif qu'il offre pour la lecture de fichier.
Nick Bastin
6

L'option -f signifie que vous ne serez pas invité si quelque chose ne se passe pas comme prévu. Cela ne signifie pas que les autorisations ne sont pas prises en compte.

Si vous ne disposez pas de suffisamment de privilèges pour supprimer un fichier, celui-ci ne sera pas supprimé.

MAIS , si vous avez assez de privilèges pour changer de privilège, votre fichier sera supprimé. C'est le cas lorsque vous êtes propriétaire d'un fichier avec des autorisations en lecture seule pour ce dernier (-r --------). En tant que propriétaire, vous pouvez chmod u+w, puis le supprimer: rm -fsupprimera ce fichier.

mouviciel
la source
5

Peut-être pourrait aider une ligne similaire avec:

touch fakefile.exe fakefile.o && rm *.o *.exe

Je sais que ce n'est pas très intelligent, mais ça fait le travail.

Bogdan
la source
3

Une alternative:

RmIfIsFile() {  for f in "$@"; do [ -f $f ] && rm $f; done; };  RmIfIsFile lexer.ml interpparse.ml interpparse.mli

Dommage que les Makefiles ne puissent pas partager les définitions de fonctions du shell sur plusieurs lignes.

Reinierpost
la source
Avez-vous essayé d'utiliser \ (barre oblique inversée) à la fin d'une ligne pour le laisser continuer à la suivante?
certain
@ some: Oui, elles peuvent être réparties sur plusieurs lignes, mais pour les partager entre des recettes, vous devez placer la définition dans une variable make.
reinierpost
3

Voici ce que j'utilise dans les scripts shell. Il cache le message d'erreur et le code d'erreur.

rm doesnotexist 2> /dev/null || echo > /dev/null
teh_senaus
la source
que diriez-vousrm doesnotexist 2&> /dev/null
user8162
1

vous pouvez toucher les fichiers avant de les récupérer. cela les créerait s'ils n'existaient pas :-)

touch lexer.ml interpparse.ml interpparse.mli
rm lexer.ml interpparse.ml interpparse.mli
brochet commun
la source
1

rm -rf ppp>/dev/null 2>&1 vous écrivez plus récent get message d'erreur Un problème survient, si une erreur ne génère pas STDERR 2 mais STDOUT 1 ... Elle se produit lorsque la commande génère non pas une erreur mais un avertissement. Vous devez définir un filtre et supprimer ce message. Mais cette affaire est ordinaire.

Anatoly
la source
1

teste pour voir si le fichier existe en premier, si c'est le cas, puis le passe à rm. Alors les erreurs de rm seront significatives. -f ou ignorer le message d'erreur est généralement plus englobant que ce qu'une personne veut. -f pourrait faire des choses que vous ne voulez pas faire.

if [ -f lexer.ml ]; then
  rm lexer.ml
fi

ajoutez plus de clauses de test s'il y a plus de fichiers dont vous voulez être sûr.


la source