Wie ändere ich die Erweiterung mehrerer Dateien?


166

Ich möchte eine Dateierweiterung von *.txtin ändern *.text. Ich habe versucht, den basenameBefehl zu verwenden, aber ich habe Probleme, mehr als eine Datei zu ändern.

Hier ist mein Code:

files=`ls -1 *.txt`

for x in $files
do
    mv $x "`basename $files .txt`.text"
done

Ich erhalte diesen Fehler:

basename: too many arguments Try basename --help' for more information

Antworten:


175

Direkt aus Gregs Wiki :

# Benennen Sie alle * .txt in * .text um
für f in * .txt; machen
    mv - "$ f" "$ {f% .txt} .text"
getan

Lesen Sie auch den Eintrag, warum Sie nicht analysieren solltenls .

Bearbeiten: Wenn Sie basenameIhre Syntax verwenden müssen, wäre:

für f in * .txt; machen
    mv - "$ f" "$ (Basisname -" $ f ".txt) .text"
getan

48
Es gibt einige leicht fortgeschrittene Bash-Syntax, die hier ohne Erklärung verwendet wird. Ich musste viele Dinge googeln, um dies vollständig zu verstehen. Um anderen in meiner Position zu helfen, finden Sie hier einige Verweise auf Globs (die *.txtSyntax) , den bloßen Doppelstrich-- und die Verwendung des% ${}-Symbols innerhalb des Konstrukts . Bis jetzt war ich den beiden letzteren noch nie begegnet und hatte nicht gewusst, was mit den ersteren wirklich geschah.
Mark Amery

3
Schauen Sie sich die Antwort von Matthias Braun unten an - viel einfacher, erreicht dasselbe.
BTK

10
One Linerfor f in *.txt; do mv -- "$f" "${f%.txt}.text"; done
Marçal Juan

1
Sie haben ein vermisstes; after text ".
Pétur Ingi Egilsson

2
@ PéturIngiEgilsson in der zweiten Zeile? Nein, das ist nicht erforderlich.
Jasonwryan

132

So ändere ich alle Dateierweiterungen im aktuellen Verzeichnis von Debian.

rename "s/oldExtension/newExtension/" *.txt

(Dies ist der Perl- renameBefehl, nicht der util-linuxeine. Siehe Warum unterscheidet sich das Umbenennungsdienstprogramm unter Debian / Ubuntu von dem auf anderen Distributionen wie CentOS? )


10
Viel einfacher als die akzeptierte Antwort, danke!
BTK

8
Auf dem Mac konnte brew install renameich das zum Laufen bringen.
Monkpit

3
Mit Fish Shell können Sie rename "s/oldExtension/newExtension/" **.txtalle * .txt rekursiv umbenennen
Palmstrom

3
Dies wird fehlschlagen für footxt.txt. Verwenden Sie stattdessen: unix.stackexchange.com/questions/19654/…
wisbucky

7
Wenn Ihre Dateien keine Erweiterung haben und Sie eine hinzufügen möchten:rename 's/$/.txt/' *
mkataja

34

Ein einfacher Befehl, der renamefromutil-linux , erledigt das für Sie und ersetzt alle Vorkommen von "txt" zu "text" in allen Dateien, die mit "* .txt" übereinstimmen:

rename txt text *.txt

4
renameÄndert das erste Vorkommen, also mach das besser rename .txt .text, aber das funktioniert immer noch nicht (zB umbenennen foo.txtx.bar.txtin foo.textx.bar.txt).
Gilles

12
Es ist zu beachten, dass nicht alle Systeme dieselbe Umbenennungsversion haben. Unter Debian und Freunden ist der renameBefehl tatsächlich perl-renameund verwendet Perl-Regexes. Dafür würde der entsprechende Befehl sein: rename 's/.txt/.text/' *.txt. Die Leute sollten das man renameauf ihrem System überprüfen , um herauszufinden, welches sie haben.
Evilsoup

@ Evilsoup Das ist der Fall für OSX, thx
Davi Lima

Dies funktioniert auch auf Cygwin (Windows)
andy

27
rename "s/oldExtension/newExtension/" *.txt

Oben funktioniert gut, ist aber auf das aktuelle Verzeichnis beschränkt. Probieren Sie den folgenden Befehl aus, der für Unterverzeichnisse flexibel ist. Alle .txtDateien in der Verzeichnisstruktur werden mit einer neuen Erweiterung umbenannt.

find . -name "*.txt" -exec rename 's/.txt$/.newext/' {} \;

2
renameKann mehrere Dateien als Argument behandeln, können Sie die Dinge erheblich beschleunigen, indem Sie verwenden, +anstatt \;wenn es viele solcher Dateien gibt
Anthon

Trotzdem ist es eine nützliche Option, da "* .txt" zu einer großen Argumentliste entrollt werden kann, die von der Shell nicht unterstützt wird.
Roman Shapovalov

1
"s / oldExtension / newExtension /" schlägt fehl für footxt.txt. Verwenden Sie stattdessen: unix.stackexchange.com/questions/19654/…
wisbucky


9

Die hier angegebenen Antworten s/oldExtension/newExtension/sind falsch. Wenn Sie verwenden s/txt/text/, würde konvertieren Sie footxt.txtzu footext.txt, das ist nicht das, was Sie wollen. Auch wenn Sie verwenden s/.txt/.text/, das wäre konvertieren footxt.txtzu fo.text.txt.

Sie müssen verwenden \., um den Punkt abzugleichen (entspricht einem .beliebigen Zeichen). Und das abschließende $, um das Ende der Linie zu entsprechen. Nur so wird die Erweiterung richtig zugeordnet.

rename 's/\.txt$/.text/' *.txt

rename 's/\.old$/.new/' *.old

7

Basierend auf der Antwort von @Prince John Wesley finden Sie hier ein einfaches Bash-Skript zum Ändern aller Dateierweiterungen im aktuellen Verzeichnis von ext1nach ext2. Gibt auch die Namen der Dateien aus, die umbenannt werden.

#!/bin/bash
for f in *.$1
do
    [ -f "$f" ] && mv -v "$f" "${f%$1}$2"
done

Beispielverwendung (unter der Annahme, dass der Name des Skripts lautet change-ext):

change-ext ext1 ext2

Um die Dateierweiterungen in Verzeichnissen rekursiv zu ändern, ersetzen Sie die zweite Zeile ( for...) durch zwei Zeilen: shopt -s globstarund for f in **/*.$1. Benötigt Bash 4+.
Dennis Golomazov

4

Grund # 53, zu zsh zu wechseln:

zmv '(*).txt' '$1.text'


3

Nehmen wir an, Ihre Dateien befinden sich in verschiedenen Verzeichnissen. Angenommen, dirx ist Ihr übergeordnetes Verzeichnis, dann erledigen Sie dies mit find:

for f in `find /dirx -iname '*.txt' -type f -print`;do  mv "$f" ${f%.txt}.text; done

Was ist mit tcsh ..
Josef Klimuk

2

Das funktioniert bei mir:

find . -name '*.txt' -exec rename 's/\.txt$/.text/' \{} \;

1
BITTE a. Hinzufügen vor dem "text"
danielmhanover

2

Wenn du

habe keine Endung für die Quelldateien

und Zielerweiterung ist .text Sie würde es auf diese Weise tun -

for f in *; do mv -- "$f" "${f%.\*}.text"; done

1
Ausgezeichnete Bash-native Schrift. hat super funktioniert! for f in *.html; do mv -- "$f" "${f%.\*}.pug"; done
TamusJRoyce

1

Für den Fall, dass Sie wissen möchten, was in Ihrer Version schief gelaufen ist: Sie haben $filesanstelle des $xBefehls basename verwendet. Das sollte also funktionieren (ungetestet):

for x in *.txt
do
  mv "$x" "`basename '$x' .txt`.text"
done
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.