Wie kann ich dafür sorgen, dass rm keinen Fehler ausgibt, wenn eine Datei nicht existiert?


329

Ich schreibe ein Makefile, das am Ende der Kompilierung einige nutzlose Dateien aufräumt. Wenn bereits ein Ziel erstellt wurde, wird dieses Ziel übersprungen, und die nutzlose Datei ist möglicherweise nicht vorhanden. Wenn ich das mache:

rm lexer.ml interpparse.ml interpparse.mli

Möglicherweise erhalte ich eine Fehlermeldung, weil eine der Dateien nicht vorhanden ist. Gibt es eine Möglichkeit rm, diese Dateien zu ignorieren?

Beim Lesen der Manpage sehe ich folgende Option:

 -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.

Das hört sich fast so an, wie ich es will, aber ich bin mir nicht sicher, was die Berechtigungen angeht. Gibt es eine Möglichkeit, dies zu tun?


Hast du welche rmin einer Sandbox probiert? Es sieht so aus, als würde -fes genau das tun, was Sie wollen, unabhängig von der Verschiebung.
JMD

Wenn die Berechtigungen dies nicht zulassen, versucht rm mit der -fOption weiterhin, es zu löschen. Es wird scheitern. Es wird Ihnen nicht sagen, dass es fehlgeschlagen ist. Nützlich, wenn der Dateiname eine Variable oder ein Glob ist.
LawrenceC

Nur der Vollständigkeit halber: Es gibt rm --interactive=neverAktionen, die so aussehen, rm -fals würde sie einen Fehler-Exit-Status zurückgeben. Weitere Informationen finden Sie hier: unix.stackexchange.com/questions/72864/…
lesmana

Antworten:


282

Die -fOption ist definitiv das, was Sie verwenden möchten.

Die Bestätigung der Dateiberechtigungen, auf die es verweist, lautet wie folgt:

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

So rmwerden Sie warnen , wenn Sie versuchen , eine Datei zu löschen , die Sie haben Schreibrechte nicht auf. Dies ist zulässig, wenn Sie über Schreibberechtigungen für das Verzeichnis verfügen, ist jedoch etwas seltsam, weshalb Sie rmnormalerweise gewarnt werden.


1
Die meisten, aber nicht alle Systeme werden fragen (glaube ich). Einige erfordern -i.
DaveParillo

1
Wenn Sie die Fehlermeldung, aber nicht den Fehlerbeendigungscode möchten, lesen Sie die Antwort von Giel Berkers . Ich verwende set -ein allen meinen Bash-Skripten, damit das Skript beendet wird, wenn ein Befehl einen Fehler ausgibt. Ich möchte oft, dass ein Skript mir mitteilt, ob rmein Fehler aufgetreten ist, aber trotzdem fortfährt. geht weiter.
Cledoux

124

Eine andere Lösung ist diese: https://stackoverflow.com/questions/11231937/bash-ignoring-error-for-a-particular-command

Fügen Sie einfach nach Ihrem Befehl eine OR-Anweisung hinzu:

rm -rf my/dir || true

Wenn die Anweisung 1 fehlschlägt (Fehler auslöst), führen Sie auf diese Weise die Anweisung 2 aus, die einfach ist true.


4
Es druckt den Fehler aus und setzt die Ausführung fort, die für meinen Fall gewünscht wurde.
worldsayshi

9
Oder rm -rf my/dir ||:um noch prägnanter zu sein ( :true
Abkürzung

Die bessere Lösung meiner Meinung nach. Es ist leicht zu erkennen, was passiert und warum der Ergebniscode ignoriert wird. Ich mag das!
Mavamaarten

76

Ich bin viel zu spät zur Party, aber ich benutze das die ganze Zeit. Fügen Sie in einem Makefile -am Anfang einer Zeile hinzu, um den Rückgabewert dieser Zeile zu ignorieren. Wie so:

-rm lexer.ml interpparse.ml interpparse.mli

9
Dadurch wird jedoch weiterhin ein Fehler an die Konsole ausgegeben, wodurch Sie trainiert werden, Fehler in der make-Ausgabe zu ignorieren. Dies ist wahrscheinlich nicht das, was Sie wollen. rm -rf ist meiner meinung nach eine bessere option.
Godsmith

@Godsmith Ich würde lieber einen Fehler ignorieren, als das rekursive Löschen zu erzwingen. Das könnte sehr ungezogen sein. Und +1 für die Makefile-spezifische Syntax
Daishi

Wenn rm -rf "ungezogen" sein könnte, bedeutet dies, dass Sie make außerhalb eines Verzeichnisses unter Versionskontrolle verwenden. Warum?
Godsmith

Bitte geben Sie einen Link zur Dokumentation an. Konnte Beschreibung dieser Funktion finden.
George Sovetov


14

Wenn Sie die Option -f nicht verwenden möchten, ist eine Alternative:

rm filethatdoesntexist 2> /dev/null 

Dies verhindert lediglich, dass Fehler gedruckt werden.


9
Leider wird dies immer noch einen Fehler-Exit-Code geben.
Shaun McDonald

8

Wenn Sie einen Weg finden, die Dateinamen zu gliedern , rmwerden Sie sich nicht beschweren, wenn keine Übereinstimmung gefunden wird. So etwas wie lexer.m* interpparse.*usw. sollte für dich funktionieren (pass auf, dass du nicht zu viel löschst). Dies -fist auch ein vernünftiger Weg, solange Sie nicht hoffen, dass Dateiberechtigungen das Löschen einer Datei verhindern, die Sie nicht löschen möchten. Wenn Sie sie nicht löschen möchten, legen Sie sie nicht ab In der Liste.


Das Globbing kommt nicht in Frage, da es eine lexer.mll-Datei gibt, die ich nicht löschen möchte. Vielen Dank, dass Sie gezeigt haben, warum -f sinnvoll ist. Ich nehme an, ich neige dazu, zu vorsichtig zu sein, nachdem ich zu viele Fehler gemacht habe sudo rm -rf.
Jason Baker

Nicht einmal einschränkender lexer.m?...? Das würde lexer.mlund fangen lexer.mz, aber nicht lexer.mlloder lexer.mla.
JMD

1
@JMD: Ich nehme an, es hängt von Ihrer Shell ab und davon, welche Unterstützung die Mustererkennung für das Globbing bietet.
Nick Bastin

6

Die Option -f bedeutet, dass Sie nicht aufgefordert werden, wenn etwas nicht erwartet wird. Dies bedeutet nicht, dass Berechtigungen nicht berücksichtigt werden.

Wenn Sie nicht über die erforderlichen Berechtigungen zum Entfernen einer Datei verfügen, wird diese nicht entfernt.

ABER , wenn Sie über genügend Berechtigungen zum Ändern von Berechtigungen verfügen, wird Ihre Datei entfernt. Dies ist der Fall, wenn Sie der Eigentümer einer Datei mit schreibgeschützten Berechtigungen für den Eigentümer sind (-r --------). Als Eigentümer können Sie es chmod u+wdann entfernen: rm -fDiese Datei wird entfernt.


5

Vielleicht könnte eine Zeile ähnlich helfen mit:

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

Ich weiß, dass dies nicht sehr klug ist, aber es macht den Job.


3

Eine Alternative:

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

Schade, dass Makefiles keine zeilenübergreifenden Shell-Funktionsdefinitionen freigeben können.


Haben Sie versucht, \ (Backslash) am Ende einer Zeile zu verwenden, um sie beim nächsten fortzusetzen?
Etwa

@some: Ja, sie können über mehrere Zeilen verteilt sein, aber um sie auf mehrere Rezepte zu verteilen, müssen Sie die Definition in eine make-Variable einfügen.
Reinierpost

3

Folgendes verwende ich in Shell-Skripten. Es verbirgt die Fehlermeldung und den Fehlercode.

rm doesnotexist 2> /dev/null || echo > /dev/null

wie wäre esrm doesnotexist 2&> /dev/null
user8162

1

Sie können die Dateien berühren, bevor Sie sie speichern. das würde sie schaffen, wenn sie nicht existieren :-)

touch lexer.ml interpparse.ml interpparse.mli
rm lexer.ml interpparse.ml interpparse.mli

1

schreibe rm -rf ppp>/dev/null 2>&1 dir neuere bekomme Fehlermeldung Problem tritt auf, wenn Fehler nicht zu STDERR 2 sondern zu STDOUT 1 generieren ... Es findet statt, wenn Befehl nicht Fehler sondern Warnung generieren. Sie müssen Filter setzen und diese Nachricht entfernen. Aber dieser Fall ist normal.


1

Testen Sie, ob die Datei zuerst vorhanden ist, und übergeben Sie sie dann an rm. Dann sind die Fehler von rm aussagekräftig. -f oder Ignorieren der Fehlermeldung ist in der Regel umfassender als das, was eine Person will. -f könnte Dinge tun, die Sie nicht erledigen möchten.

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

Fügen Sie weitere Testklauseln hinzu, wenn Sie sicher sein möchten, dass weitere Dateien vorhanden sind.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.