Ich möchte Dateien umbenennen, um ihre Erweiterung zu ändern
mv *.txt *.tsv
Aber wenn ich das tue, bekomme ich:
* .tsv ist kein Verzeichnis
Ich finde es etwas seltsam, dass die ersten 10 Google-Hits mvso funktionieren sollten.
Ich möchte Dateien umbenennen, um ihre Erweiterung zu ändern
mv *.txt *.tsv
Aber wenn ich das tue, bekomme ich:
* .tsv ist kein Verzeichnis
Ich finde es etwas seltsam, dass die ersten 10 Google-Hits mvso funktionieren sollten.
Antworten:
Wenn Sie den Befehl ausgeben:
mv *.txt *.tsv
Nehmen wir an, die Shell erweitert die Platzhalter, wenn übereinstimmende Dateien (einschließlich Verzeichnisse) vorhanden sind. Die Liste der Dateien wird hier an das Programm übergeben mv. Wenn keine Übereinstimmungen gefunden werden, wird die nicht erweiterte Version übergeben.
Nochmals: Die Shell erweitert die Muster, nicht das Programm.
Viele Beispiele sind vielleicht der beste Weg, also los geht's:
$ ls
file1.txt file2.txt
$ mv *.txt *.tsv
Nun , was auf das geschieht , mvist , dass die Shell erweitert *.txtmit den entsprechenden Dateien. Da gibt es keine *.tsvDateien, die nicht geändert werden.
Der mvBefehl wird mit zwei speziellen Argumenten aufgerufen :
argc: Anzahl der Argumente, einschließlich des Programms.argv: Ein Array von Argumenten, einschließlich des Programms als ersten Eintrag.Im obigen Beispiel wäre das:
argc = 4
argv[0] = mv
argv[1] = file1.txt
argv[2] = file2.txt
argv[3] = *.tsv
Das mvProgramm prüft, ob das letzte Argument *.tsvein Verzeichnis ist. Da dies nicht der Fall ist, kann das Programm nicht fortgesetzt werden, da es nicht zum Verketten von Dateien vorgesehen ist. (Verschieben Sie in der Regel alle Dateien in eine.) Erstellen Sie keine Verzeichnisse aus einer Laune heraus.
Als Ergebnis bricht es ab und meldet den Fehler:
mv: target ‘*.tsv’ is not a directory
Nun, wenn Sie stattdessen sagen:
$ mv *1.txt *.tsv
Der mvBefehl wird ausgeführt mit:
argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[2] = *.tsv
mvÜberprüfen Sie nun erneut, ob *.tsvvorhanden. Da dies nicht der Fall ist, wird die Datei file1.txtnach verschoben *.tsv. Das heißt: Die Datei wird in *.tsvmit dem Stern und allem umbenannt.
$ mv *1.txt *.tsv
‘file1.txt’ -> ‘*.tsv’
$ ls
file2.txt *.tsv
Wenn Sie stattdessen sagten:
$ mkdir *.tsv
$ mv *.txt *.tsv
Der mvBefehl wird ausgeführt mit:
argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[1] = file2.txt
argv[2] = *.tsv
Da es sich *.tsvnun um ein Verzeichnis handelt, werden die Dateien dorthin verschoben.
Nun: Mit Befehlen wie some_command *.tsvwenn die Absicht besteht, den Platzhalter tatsächlich beizubehalten, sollte man ihn immer zitieren. Durch das Zitieren verhindern Sie, dass die Platzhalter erweitert werden, falls Übereinstimmungen auftreten sollten. ZB sagen mkdir "*.tsv".
Die Erweiterung kann weiterhin angezeigt werden, wenn Sie beispielsweise Folgendes tun:
$ ls
file1.txt file2.txt
$ mkdir *.txt
mkdir: cannot create directory ‘file1.txt’: File exists
mkdir: cannot create directory ‘file2.txt’: File exists
Jetzt: Der mvBefehl kann und kann mit mehreren Dateien arbeiten. Wenn es aber mehr als zwei gibt, muss das letzte ein Zielverzeichnis sein. (Optional können Sie die -t TARGET_DIROption zumindest für GNU mv verwenden.)
Das ist also OK:
$ ls -F
b1.tsv b2.tsv f1.txt f2.txt f3.txt foo/
$ mv *.txt *.tsv foo
Hier mvwürde aufgerufen werden mit:
argc = 7
argv[0] = mv
argv[1] = b1.tsv
argv[2] = b2.tsv
argv[3] = f1.txt
argv[4] = f2.txt
argv[5] = f3.txt
argv[6] = foo
und alle Dateien landen im Verzeichnis foo.
Wie für Ihre Links. Sie haben eine (in einem Kommentar) angegeben, wo überhaupt mvnicht erwähnt wird, aber rename. Wenn Sie mehr Links haben, können Sie diese teilen. Dies gilt auch für Manpages, auf denen Sie behaupten, dass dies zum Ausdruck gebracht wird.
Ich weiß, dass dies Ihre Frage nicht beantwortet, aber falls Sie nach einer anderen Möglichkeit suchen, die Dateien im Vergleich zu Ihrer Umgehungsschleife umzubenennen, warum nicht find? Ich habe diesen Befehl oft verwendet, um Dateierweiterungen in großen Verzeichnissen durch Hunderttausende von Dateien zu ersetzen. Dies sollte auf jedem POSIX-kompatiblen System funktionieren:
find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;
Befehlsaufschlüsselung:
'
.' => Suchpfad ab aktuellem Verzeichnis mit '. '
-name=> find match name setzen (in diesem Fall alle Dateien, die mit enden.gappedPeak)
-exec=> führe bei jedem Treffer den folgenden Befehl aus
sh -c=> 'exec' erstellt für jede Übereinstimmung eine unabhängige Shell-Umgebung
mv "$1" "${1%.gappedPeak}.bed"=>mverste Variable (bezeichnet mit $ 1 ), die der aktuelle Dateiname ist, zu neuem Namen. Hier mache ich einen Teilstring-Abgleich und lösche; Nehmen Sie also erneut die erste Variable, $ 1, und verwenden Sie%, um sie.gappedPeakaus der Zeichenfolge zu löschen . Die.bedam Ende verkettet nur die verbleibende Variable, die jetzt nur mit den neuen zu schaffen Dateinamen.test#.bedtest#.bedDer Unterstrich ist ein Platzhalter für $ 0
Das
{}wird durch jeden (*.gappedPeak) Dateinamen ersetzt, den derfindBefehl gefunden hat, und wird zu $ 1 für denshBefehl.
\;markiert das Ende des-execBefehls. Sie können auch';'oder verwenden";".
Beispiel:
[user@before]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.gappedPeak
[user@after]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.bed
file.abc-> blub.xyzin mehreren Unterverzeichnissen:find . -name "file.abc" -exec sh -c 'mv "$1" "$(dirname $1)/blub.xyz"' _ {} \;
mv *.txt *.tsvfunktioniert nicht; mvkann jeweils nur eine Datei umbenennen. Sie haben die Erklärungen entweder falsch verstanden oder sie sind falsch.
mmvund renamekann mehrere Dateien gleichzeitig umbenennen. Es gibt jedoch zwei Versionen von, renamedie unterschiedlich bezeichnet werden. Es sollte hier viele Fragen dazu geben.
rename, nicht mv.
mv *.txt *.tsv mv(normalerweise) nicht sehen *.txtoder *.tsvaber die Shell-erweiterten Dateinamen. Die Anzahl der Dateien, auf die diese Platzhalterzeichen erweitert werden, ist "zufällig". Dies funktioniert nur, wenn eine Datei mit dem Namen vorhanden *.txtist, der (wörtlich) umbenannt werden soll *.tsv(ohne Anführungszeichen darf die bashOption nullglobnicht gesetzt sein).
foo.txtund eine mit dem Namen baz.tsvthe hat, mv *.txt *.tsvwird die vorhandene .tsvDatei überschrieben ...
Wenn Sie beispielsweise asd.txtund qwe.txtDateien im Verzeichnis haben, während Sie den Befehl ausführen mv *.txt *.tsv, wird versucht, diese beiden Dateien in ein Verzeichnis mit dem Namen zu verschieben *.tsv. Da es kein solches Verzeichnis gibt, wird ein Fehler ausgegeben.
rename(1)renameist ein Perl-Skript von Larry Wall, dem Hersteller von Perl. Es benötigt einen Perl-Regex und verarbeitet den Dateinamen.
rename 's/\.txt$/.tsv/' *.txt
Wenn Sie renameunter Debian / Ubuntu installieren müssen, können Sie dies tun
sudo apt install rename
Eine weitere Option ist die Verwendung von:
cp -p *.txt *.tsv
rm -f *.txt
*.txtDateien nach kopiert , *.tsvwobei ihre Attribute mit dem -pFlag beibehalten werden.*.txtmvdie, mit der einfach / directory / filename geändert wird, ohne die Dateien tatsächlich zu verschieben, es sei denn, sie befinden sich auf einer anderen Partition.