Ein Befehl wie mv foo* ~/bar/
erzeugt diese Nachricht in stderr, wenn keine passenden Dateien vorhanden sind foo*
.
mv: cannot stat `foo*': No such file or directory
In dem Skript, an dem ich arbeite, wäre dieser Fall jedoch völlig in Ordnung, und ich würde diese Nachricht gerne aus unseren Protokollen streichen.
Gibt es eine nette Möglichkeit, mv
ruhig zu sein, auch wenn nichts bewegt wurde?
mv foo* ~/bar/ 2> /dev/null
?mv
. :) Aber das reicht natürlich.mv
Implementierungen eine-q
Option unterstützen, um sie zu beruhigen, aber das ist nicht Teil der POSIX-Spezifikation fürmv
. Diemv
in GNU coreutils, zum Beispiel, hat nicht haben eine solche Option.Antworten:
Suchen Sie das?
quelle
set -e
(der in jedem Shell-Skript verwendet werden sollte) fehl. Sie können ein hinzufügen|| true
, um die Prüfung für einen einzelnen Befehl zu deaktivieren.set -e
sollte nicht in jedem Shell-Skript verwendet werden. In vielen Fällen wird das Fehlermanagement dadurch noch komplexer als ohne.Eigentlich halte ich Muting nicht für
mv
einen guten Ansatz (denken Sie daran, es könnte Sie auch über andere Dinge informieren, die von Interesse sein könnten ... zB fehlende~/bar
). Sie möchten es nur stumm schalten, wenn Ihr Glob-Ausdruck keine Ergebnisse liefert. Eigentlich lieber gar nicht ausführen.Sieht nicht sehr ansprechend aus und funktioniert nur in
bash
.ODER
nur außer du bist
bash
mitnullglob
set dabei. Sie zahlen jedoch einen Preis von 3x Wiederholung des Glob-Musters.quelle
foo*
wenn sie die einzige im aktuellen Verzeichnis ist, die mit dem Glob übereinstimmtfoo*
. Dies kann mit einem Glob-Ausdruck umgangen werden, der sich nicht im wahrsten Sinne des Wortes anpasst. Eg[ 'fo[o]*' = "$(echo fo[o]*)" ] || mv fo[o]* ~/bar/
.find . -maxdepth 1 -name 'foo*' -type f -print0 | xargs -0r mv -t ~/bar/
- GNU's
mv
hat die nette Option "destination first" (-t
) undxargs
kann die Ausführung seines Befehls überspringen, wenn überhaupt keine Eingabe erfolgt (-r
). Die Verwendung von-print0
und stellt-0
dementsprechend sicher, dass es nicht zu Unordnung kommt, wenn Dateinamen Leerzeichen und andere "lustige" Dinge enthalten.quelle
-maxdepth
,-print0
,-0
und-r
sind auch GNU - Erweiterungen (obwohl einige von ihnen in anderen Implementierungen heute zu finden sind).mv
.Es ist wichtig zu wissen , dass es tatsächlich die Shell ist, die das
foo*
auf die Liste der übereinstimmenden Dateinamen erweitert, so dass sich selbst wenigmv
tun kann.Das Problem hierbei ist, dass, wenn ein Glob nicht übereinstimmt, einige Shells
bash
(und die meisten anderen Bourne-ähnlichen Shells, die in den späten 70er Jahren von der Bourne-Shell eingeführt wurden) das Muster wörtlich an den Befehl übergeben.Also hier, wenn
foo*
keine Datei entspricht, anstatt den Befehl Abbruch (wie Pre-Bourne - Shells und mehrere modernen Schalen tun), so geht die Schale eine wortgetreuefoo*
Datei aufmv
, so dass im Grunde fragtmv
genannt , die Datei zu bewegenfoo*
.Diese Datei existiert nicht. Wenn dies der Fall wäre, hätte es tatsächlich mit dem Muster überein- gestimmt, sodass
mv
ein Fehler gemeldet wird. Wäre das Musterfoo[xy]
stattdessen gewesen,mv
hätte man versehentlich eine aufgerufene Dateifoo[xy]
anstelle derfoox
undfooy
-Dateien verschieben können.Selbst in Shells, die dieses Problem nicht haben (vor Bourne, csh, tcsh, fish, zsh, bash -O failglob), wird immer noch ein Fehler angezeigt,
mv foo* ~/bar
diesmal jedoch von der Shell.Wenn Sie möchten, dass es kein Fehler ist, wenn keine Datei gefunden wurde,
foo*
und in diesem Fall nichts verschieben möchten, sollten Sie zuerst die Liste der Dateien erstellen (auf eine Weise, die keinen Fehler verursacht, wie mit dernullglob
Option von einige Muscheln), und dann nur aufrufen,mv
ist die Liste nicht leer.Das wäre besser, als alle Fehler zu verbergen
mv
(als2> /dev/null
würde das Hinzufügen ), als obmv
es aus irgendeinem anderen Grund fehlschlagen würde. Sie würden wahrscheinlich immer noch wissen wollen, warum.in zsh
Oder verwenden Sie eine anonyme Funktion, um die Verwendung einer temporären Variablen zu vermeiden:
zsh
ist eine dieser Shells, die den Bourne-Fehler nicht aufweisen und einen Fehler melden, ohne den Befehl auszuführen, wenn ein Glob nicht übereinstimmt (und dienullglob
Option nicht aktiviert wurde). Hier können Sie also denzsh
Fehler ausblenden und wiederherstellen stderr fürmv
so würden Sie immer noch diemv
Fehler sehen, wenn überhaupt, aber nicht den Fehler über die nicht passenden Globs:Oder Sie könnten verwenden,
zargs
was auch Probleme vermeidenfoo*
würde, wenn der Glob zu man-Dateien erweitern würde.In ksh93:
In der Bash:
bash
Es gibt keine Syntax, die nurnullglob
für einen Glob aktiviert werden kann , und diefailglob
Option wird deaktiviert,nullglob
sodass Sie Folgendes benötigen:oder setzen Sie die Optionen in einer Subshell, um sie zu speichern, bevor Sie sie speichern und anschließend wiederherstellen müssen.
Im
yash
Im
fish
In der Fish Shell ist das Nullglob-Verhalten die Standardeinstellung für den
set
Befehl.POSIXly
nullglob
In POSIX gibt es keine Optionsh
und kein Array außer den Positionsparametern. Es gibt jedoch einen Trick, mit dem Sie feststellen können, ob ein Glob übereinstimmt oder nicht:Wenn Sie sowohl a
foo[*]
als auchfoo*
glob verwenden, können Sie zwischen dem Fall, in dem es keine übereinstimmende Datei gibt, und dem Fall, in dem es eine Datei gibt, die zufällig aufgerufen wirdfoo*
(was einset -- foo*
nicht tun kann), unterscheiden.Lesen Sie weiter:
quelle
Es ist wahrscheinlich nicht das Beste, aber Sie können den
find
Befehl verwenden, um zu überprüfen, ob der Ordner leer ist oder nicht:quelle
foo*
Suchpfad gebenfind
.Ich gehe davon aus, dass Sie bash verwenden, da dieser Fehler vom Verhalten von bash abhängt, um nicht übereinstimmende Globs für sich selbst zu erweitern. (Im Vergleich dazu löst zsh einen Fehler aus, wenn versucht wird, ein nicht übereinstimmendes Glob zu erweitern.)
Was ist also mit der folgenden Problemumgehung?
Dies wird leise die ignorieren ,
mv
wennls -d foo*
fehlschlägt, während immer noch Fehler Protokollierung , wennls foo*
gelingt , aber diemv
fehlschlägt. (Vorsicht,ls foo*
kann aus anderen als denfoo*
nicht vorhandenen Gründen fehlschlagen , z. B. aufgrund unzureichender Rechte, eines Problems mit dem FS usw., sodass solche Bedingungen von dieser Lösung unbemerkt ignoriert werden.)quelle
bash
). +1 für die Berücksichtigung der Tatsache, dassmv
aus anderen Gründen alsfoo*
nicht vorhanden fehlschlagen könnte .ls
ziemlich ausführlich ist und der Sinn des Befehls für zukünftige Leser zumindest ohne Kommentar nicht sehr klar ist.)ls -d foo*
könnte auch aus anderen Gründen mit einem Exit-Status ungleich Null zurückkehren, z. B. nach aln -s /nowhere foobar
(zumindest bei einigenls
Implementierungen).Sie können zum Beispiel tun
mv 1>/dev/null 2>&1 foo* ~/bar/
odermv foo* ~/bar/ 1&>2
Weitere Informationen finden Sie unter: http://mywiki.wooledge.org/BashFAQ/055
quelle
mv foo* ~/bar/ 1&>2
Bringt den Befehl nicht zum Schweigen, sondern sendet das, was auf stdout gewesen wäre, um auch auf stderr zu sein./dev/null
durchNUL
1
und zu2
bedeuten?Sie können (portabel) betrügen mit
perl
:quelle
Wenn Sie Perl verwenden möchten, können Sie genauso gut den ganzen Weg gehen:
oder als Einzeiler:
(Einzelheiten zum
move
Befehl finden Sie in der Dokumentation zu File :: Copy .)quelle
Stattdessen
du kannst tun
Einfach, lesbar :)
quelle
cp
nochrm
schweigen , wennfoo*
nicht existiert.Ob der obige Befehl erfolgreich ist oder nicht, können wir durch Beenden des vorherigen Befehls feststellen
ob die Ausgabe von echo $? ist anders als 0 bedeutet, dass der Befehl nicht erfolgreich ist, wenn die Ausgabe 0 ist, bedeutet, dass der Befehl erfolgreich ist
quelle