Ich habe gerade einen kleinen Teil meiner Audiosammlung durch einen blöden Fehler verloren. :-(
GLADLY Ich hatte ein ziemlich aktuelles Backup, aber es war immer noch ärgerlich. Abgesehen von deinem, war der andere Schuldige, der das Unheil angerichtet hat, der folgende Beweis mv
:
Die Audiodateien hatten ein bestimmtes Schema:
ARTIST - Some Title YY.mp3
Wo YY
ist die zweistellige Jahresangabe?
mkdir 90<invisible control character>
(Bis zu diesem Moment wusste ich nicht, dass ich tatsächlich ein Drittel überschüssigen Zeichens eingegeben hatte, das unsichtbar war ...!)
Anstatt alles in einem Verzeichnis zu haben, wollte ich alle Musik der 90er Jahre in einem Verzeichnis haben. Also schrieb ich:
find . -name '* 9?.mp3' -exec mv {} 90 \;
Nicht so schwer, die Idee zu bekommen, was eh passiert ist? : ->
Das (katastrophale) Ergebnis war ein jungfräuliches leeres Verzeichnis mit dem Namen '90 something '(wobei etwas das "unsichtbare" Steuerzeichen ist) und eine einzelne Datei mit dem Namen' 90 ', die n- mal überschrieben wurde.
ALLE DATEIEN WURDEN GEGANGEN. : - (((offensichtlich)
Ich wünschte mv
, ich hätte rechtzeitig überprüft, ob die Signatur der Zieldatei (bitte beachten Sie * NIX: Everything Is A File ) mit einem d------
(z drwxr-xr-x
. B. ) beginnt . Und natürlich, ob das Ziel überhaupt existiert . Es ist eine Variante des oben genannten Szenarios, wenn man einfach vergessen zu mkdir
erstem Verzeichnis. (aber natürlich hast du angenommen, dass es da ist ...)
Sogar unser Hass-Betriebssystem, das mit der Hauptstadt W beginnt, tut dies. Sie werden sogar aufgefordert , den Zieltyp (Datei? Verzeichnis?) Anzugeben, wenn Sie danach fragen.
Daher frage ich mich, ob wir * NIXer uns noch ein " mv
Scriptlet" schreiben müssen , um diese Art von unerwünschten Überraschungen zu vermeiden.
.mp3
mit dem Namen vorhanden sein90
, es könnte einer gewesen sein, für den Sie kein Backup hatten.mv
Technisch gesehen ist dies nicht das Problem, da nicht bekannt ist, dass Sie eine Reihe von Dateien verschieben. Sie werdenmv
einmal für jede Datei ausgeführt. Sofind -exec ;
funktioniert es. Wenn Sie verwendet hättenfind -exec +
(wie in einigen Kommentaren)mv
würde hätte es geschrien, sobald es mehr als ein Argument bekommen hätte.mv
für jede einzelne Datei auf den ersten Blick weniger durchdacht erscheint, wird es (wie ich bereits sagte) die einzig vernünftige Lösung sein, wenn die Quelldateien auf verschiedene Unterverzeichnisse verteilt sind. Dass sich in meinem Testfall alle Quelldateien in einem Verzeichnis befanden, bedeutet nicht, dass es sich um meinen eigentlichen Testfall handelt. Es ist in der Tat nur eine Vereinfachung, da ich das später leicht selbst ausführen kann. Darüber hinaus ist das Lesen von Fragen aufgrund der kürzeren Länge weniger zeitaufwändig. :)mv
, dass das Ziel existiert?mv oldfile newfile
ist der Weg, eine Datei umzubenennen, und es ist albern zu erwartennewfile
, dass sie bereits existiert und ein Verzeichnis ist.Antworten:
Sie können ein
/
an das Ziel anhängen , wenn Sie Dateien in ein Verzeichnis verschieben möchten. Falls das Verzeichnis nicht existiert, erhalten Sie eine Fehlermeldung:Falls das Verzeichnis existiert, verschiebt es die Datei in dieses Verzeichnis.
quelle
Das GNU-Coreutils hat
mv
bereits eine Option, die angibt, dass Sie in ein Verzeichnis verschieben möchten:-t
/--target-directory
. Wenn das Argument für diese Option nicht vorhanden ist,mv
werden Sie sich beschweren, anstatt alle Ihre Dateien in den gleichen Dateinamen zu verschieben.Ich hätte deinen Urheber wie folgt geschrieben:
Beachten Sie, dass
+
stattdessen\;
so viele Dateinamen wie möglich zusammengefasst werden, was zu einer schnelleren Ausführung führt.quelle
find . -name '* 9?.mp3' -exec sh -c 'exec mv "$@" 90/' sh {} +
Wenn Sie in Zukunft generell ein versehentliches Überschreiben vermeiden möchten, gibt es die
-i
Option fürmv
. Ich persönlich kann mir keine Nachteile vorstellen, wenn SieWenn Sie dann etwas überschreiben müssen, übergeben Sie einfach die
-f
Option.Aliase werden nur wirksam, wenn Sie den Befehl direkt in eine interaktive Shell eingeben, nicht in Fällen wie dem Aufruf durch
find
. Du hättest laufen könnenund dann wären Sie gefragt
mv
worden, ob Sie versucht hätten, eine vorhandene Datei zu überschreiben.quelle
mv
. Dieser weniger bekannte „Trick“ bewirkt , dass der Befehl mit dem umgekehrten Schrägstrich vorangestellt zu ignorieren alle Alias - Definitionen.find ... -exec mv ...
, ein~/bin/mv
Verzeichnis erstellen (oder ein anderes geeignetes Verzeichnis) und es erstellen lassen/bin/mv -i "$@"
- weil Siefind ... -exec
sich keine Aliase ansehen.env mv
. Weniger tippen. :) Da für mein lokales Tastaturlayout das Drücken der UMSCHALTTASTE für einen Schrägstrich erforderlich ist, würde ich (falls zutreffend) immer "Schrägstrichlose" Versionen bevorzugen.mv
an einem Ort am Anfang$PATH
eine sauberere Lösung wäre. Auf der anderen Seite passiere ich vor allemmv
sorglos in der interaktiven Shell (weil es schnell geht). In dem Moment, in dem ich etwas Komplexeres komponiere, wiefind
einefor
Schleife oder sogar ein Shell-Skript, tendiere ich dazu, ein paar Probeläufe (mitecho
) durchzuführen, um sicherzustellen, dass ich nichts kaputt mache. In solchen Fällen brauche ich kein Händchenmv
, weil ich mir schon Gedanken mache.Zusätzlich zu den hervorragenden Antworten oben möchte ich klären, warum Sie nicht die Frage haben, ob Sie die Dateien verschieben sollen oder nicht.
Wenn Sie eine Datei an einen neuen Namen verschieben und dieser Name kein Verzeichnis ist,
mv
wird Ihre Datei in den neuen Namen umbenannt.Das Problem hierbei ist , dass Sie wurden unter Verwendung
find
auszuführenmv
einmal pro Datei , nicht einmal für alle Dateien .Wenn Sie es stattdessen getan hätten
mv *90.mp3 90
, dannmv
wäre die Fehlermeldung "Die Zieldatei ist kein Verzeichnis" fehlgeschlagen.Ein weiterer Ratschlag ist die Verwendung der Tabulatorvervollständigung beim Eingeben des Zielpfads. Durch Hinzufügen
/
zum Zielnamen wird angezeigt, ob das Ziel ein Verzeichnis ist . Sie können auchmv -i
mit gefragt werden, ob Sie eine vorhandene Datei überschreiben möchten.quelle
mv *90.mp3 90
, wäre mv mit der Fehlermeldung "Die Zieldatei ist kein Verzeichnis" fehlgeschlagen. Hah ja warum so kompliziert eh Ich benutze deine Leitung und ich werde glücklich sein. Nur in diesem trivialen Fall. :) Weil das die normale Art ist, wie ich meine Fragen stelle: Ich hätte sie der Einfachheit halber eingegrenzt. Bisher hat niemand etwas dagegen einzuwenden,find
dass die Dateien der 90er Jahre genauso gut in verschiedenen Unterverzeichnissen verstreut sind, die ich ebenfalls "fangen" möchte. Wenn und nur wenn sie sich immer in einem Quellverzeichnis befinden, ist Ihremv
Zeile anwendbar.mv
und nicht als Kritik an der Auswahl der Tools.find
undmv
z. B.find /music -type d -exec mv {}/*90.mp3 targetdir\;
- aber jetzt habe ich das Gefühl, dass ich es zu kompliziert mache und einfach-i
oder-t
effizienter benutzefind . -type d -exec mv {}/*9?.mp3 target \;
Beispiel funktioniert, besteht immer noch das Risiko, dass dermv
Befehlmv file target
für jedes Verzeichnis, das nur eine*9?.mp3
Datei enthält, so aussieht . Alle diese Dateien (mit Ausnahme der letzten) würden verloren gehen.*.mp3
Dateien in einem Verzeichnisbaum etwas anfangen möchten , können Sieshopt -s globstar
Ihren Befehl ausführen**/*.mp3
- der**
Wille verhält sich wie einfind
.Als alternative Allzweckstrategie möchte ich vorschlagen, diese Art von Operation in ein temporäres Skript umzuwandeln. Ich ziehe es vor, die Ergebnisse zu betrachten
find
und siemv
von Hand in einen Befehl umzuwandeln, um sicherzustellen, dass ich verstehe, was ich tue, bevor ich sie ausführe. z.B.Jetzt kann ich eine Liste der Dateinamen durchsehen und den Dateiinhalt als Shell-Befehl neu schreiben.
ggVGJ
Imv
[esc]
Asomedir/
[esc]
source tmp
in der Befehlszeile aus.Es ist eine konservative Strategie, aber ich habe von vertippte zu oft gebissen worden
-exec
odersed
Befehlen oder falsch verstehen Shell - Erweiterungen, und ich ziehe einen langsamen konsequenten Ansatz.Mit anderen Worten: Ich bin zu feige, um es zu gebrauchen
-exec
.quelle
:%s/.*/"&"/
Schritt weggelassen, weil Sie in diesem Fall wissen, dass jeder Dateiname mindestens ein Leerzeichen enthält.echo mv
stattmv
und anschließendes Entfernen der Option ,echo
wenn Sie zufrieden sind.Andere Option:
Es ist dasselbe wie -i, aber es wird nicht gefragt, es wird scheitern.
quelle