web-dev-qa-db-de.com

bash-Fehler beim Umbenennen von Dateien mit Leerzeichen - MV-Ziel ist kein Verzeichnis

Ich versuche, eine Reihe von Dateien, die Leerzeichen enthalten, umzubenennen, um die Leerzeichen zu entfernen. Ich dachte, ich hätte den richtigen Bash-Befehl gefunden:

for f in *.txt; do mv \"$f\" ${f/ /}; done

Dies gibt jedoch den Fehler "mv: target ist kein Verzeichnis" für jede Datei. Wenn ich im Befehl 'mv' durch 'echo mv' ersetze, wird der richtige mv-Befehl für jede Datei ausgegeben, und wenn ich einen dieser mv-Befehle einzeln eingebe, funktionieren sie. Wenn ich zum Beispiel 2 Dateien "a .txt" und "b .txt" habe und den obigen Befehl ausführe, erhalte ich:

mv: target 'a.txt' is not a directory
mv: target 'b.txt' is not a directory

Wenn ich den Befehl eingebe:

for f in *.txt; do echo mv \"$f\" ${f/ /}; done

Ich bekomme:

mv "a .txt" a.txt
mv "b .txt" b.txt

Ich habe einen anderen Weg gefunden, dies mit "Umbenennen" zu tun, aber ich möchte wissen, warum dies nicht funktioniert.

9
Jim Hines

Versuchen:

for f in *.txt; do mv "$f" "${f// /}"; done

Drei Punkte:

  1. Die Anführungszeichen um eine Shell-Variable sollten nicht maskiert werden.

  2. Im Allgemeinen empfiehlt es sich, jeden Verweis auf eine Shell-Variable in doppelte Anführungszeichen zu setzen.

  3. ${f/ /} entfernt nur das erste Vorkommen eines Leerzeichens. Verwenden Sie ${f// /}, um alle Leerzeichen zu entfernen.

Was schief gelaufen ist

$ touch {a,b}" .txt"
$ ls *.txt
a .txt  b .txt
$ for f in *.txt; do mv \"$f\" ${f/ /}; done
mv: target `a.txt' is not a directory
mv: target `b.txt' is not a directory

Der Ausdruck \"$f\" verhält sich nicht wie doppelte Anführungszeichen. Es wird auf zwei Argumente erweitert, z. B. "a und .txt", wobei die doppelten Anführungszeichen wie normale Zeichen behandelt werden, genau wie die a ein normales Zeichen ist. Da es drei Argumente für mv gibt ("a und .txt" und a.txt), ist mv der Ansicht, dass Sie versuchen, die ersten beiden Argumente in das dritte zu verschieben, und das dritte muss ein Verzeichnis sein. Da das dritte Verzeichnis kein Verzeichnis ist, wird eine Fehlermeldung ausgegeben.

21
John1024

Da dies die erste Sache ist, die bei Google aufgetaucht ist, als dieser Fehler gegoogelt wurde, dachte ich, ich würde ein bisschen hinzufügen.

Dieser Fehler tritt auf, wenn Sie mehr als zwei Argumente haben und das letzte Ergebnis kein Verzeichnis ist.

Das funktioniert:

mv file1.txt output.txt

Das tut nicht:

mv file1.txt file2.txt

In meinem Fall habe ich Folgendes ausgeführt: mv prefix_* output_file_name um sicherzustellen, dass eine heruntergeladene Datei einen konsistenten Namen hat, aber eine andere Datei im Verzeichnis angezeigt wurde. Dies hat zur Folge, dass der Fehler "mv target is not a directory" (MV-Ziel ist kein Verzeichnis) angezeigt wird

0
sdfgeoff