Antworten:
Eine bessere Lösung (mit nur Bash-Funktionalität im Gegensatz zu externen Anrufen) finden Sie in einer der anderen Antworten .
Folgendes würde erfordern und nicht erfordern, dass das System das rename
Programm hat (obwohl Sie dies am häufigsten auf einem System haben würden):
for file in *.html; do
mv "$file" "$(basename "$file" .html).txt"
done
BEARBEITEN: Wie in den Kommentaren erwähnt, funktioniert dies nicht für Dateinamen mit Leerzeichen ohne korrektes Anführungszeichen (jetzt oben hinzugefügt). Wenn Sie nur an Ihren eigenen Dateien arbeiten, von denen Sie wissen, dass sie keine Leerzeichen in den Dateinamen enthalten, funktioniert dies. Wenn Sie jedoch etwas schreiben, das zu einem späteren Zeitpunkt wiederverwendet werden kann, überspringen Sie nicht das richtige Anführungszeichen.
ren *.a *.b
$()
Syntax anstelle der alten Backtick-Syntax. Verbessert die Lesbarkeit und macht die Syntax weniger eindeutig, wenn Sie Zeichen haben, für die ein Backslash-Escape erforderlich wäre, um innerhalb der Befehlsersetzung durch letztere wörtlich zu sein.
Wenn Sie bash verwenden, sind keine externen Befehle wie sed, basename, rename, expr usw. erforderlich.
for file in *.html
do
mv "$file" "${file%.html}.txt"
done
"${file%.*}.txt"
, kann dies für Dateien ohne Erweiterung gefährlich sein.
$
in den geschweiften Klammern keine befindet !
--
"Operator": mv - "$ file" "$ {file% .html} .txt" Dieser Operator verhindert Dateinamen, die mit beginnen ein '-' von mv als Argumente analysiert.
rename 's/\.html$/\.txt/' *.html
macht genau das, was Sie wollen.
Dies funktionierte für mich unter OSX von .txt bis .txt_bak
find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;
.txt
zu zu gehen , müssen .txt_bak
Sie nur verketten _bak
;)
.scss
in .sass
(nach In-Place-Konvertierung…):find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \;
Sie möchten verwenden rename
:
rename -S .html .txt *.html
Dies ist genau das, was Sie wollen - es wird die Erweiterung ändern aus , .html
um .txt
für alle Dateien Matching *.html
.
Hinweis: Greg Hewgill weist korrekt darauf hin, dass dies keine eingebaute Bash ist. und ist ein separater Linux-Befehl. Wenn Sie nur etwas unter Linux benötigen, sollte dies gut funktionieren. Wenn Sie etwas plattformübergreifenderes benötigen, schauen Sie sich eine der anderen Antworten an.
rename
Programm nicht mit bash
allen Plattformen verbunden und auch nicht auf allen Plattformen verfügbar. Ich habe es nur unter Linux gesehen.
rename -S .html .text *.html
wo -S
steht für--subst-all
Auf einem Mac ...
brew install rename
rename -S .html .txt *.html
Für Ubuntu-Benutzer:
rename 's/\.html$/\.txt/' *.html
Dies ist die schickste Lösung, die ich gefunden habe und die unter OSX und Linux funktioniert, und sie funktioniert auch gut mit Git!
find . -name "*.js" -exec bash -c 'mv "$1" "${1%.js}".tsx' - '{}' \;
und mit git:
find . -name "*.js" -exec bash -c 'git mv "$1" "${1%.js}".tsx' - '{}' \;
Hier ist ein Beispiel für den Umbenennungsbefehl:
rename -n ’s/\.htm$/\.html/’ *.htm
Das -n bedeutet, dass es sich um einen Testlauf handelt und keine Dateien geändert werden. Es wird eine Liste der Dateien angezeigt, die umbenannt würden, wenn Sie das -n entfernen würden. Im obigen Fall werden alle Dateien im aktuellen Verzeichnis von einer Dateierweiterung von .htm in .html konvertiert.
Wenn die Ausgabe des obigen Testlaufs in Ordnung aussah, können Sie die endgültige Version ausführen:
rename -v ’s/\.htm$/\.html/’ *.htm
Das -v ist optional, aber es ist eine gute Idee, es einzuschließen, da es der einzige Datensatz ist, den Sie über Änderungen haben, die mit dem Umbenennungsbefehl vorgenommen wurden, wie in der folgenden Beispielausgabe gezeigt:
$ rename -v 's/\.htm$/\.html/' *.htm
3.htm renamed as 3.html
4.htm renamed as 4.html
5.htm renamed as 5.html
Der schwierige Teil in der Mitte ist eine Perl-Substitution mit regulären Ausdrücken, die unten hervorgehoben wird:
rename -v ’s/\.htm$/\.html/’ *.htm
In dieser Frage wird Bash ausdrücklich erwähnt, aber wenn Sie ZSH zur Verfügung haben, ist dies ziemlich einfach:
zmv '(*).*' '$1.txt'
Wenn Sie zsh: command not found: zmv
dann einfach laufen:
autoload -U zmv
Und dann versuchen Sie es erneut.
Vielen Dank an diesen Originalartikel für den Tipp zu zmv.
Nach dem Crawlen der Website einer anderen Person fehlten mir Tausende von Dateien mit der Erweiterung .html in einem breiten Baum von Unterverzeichnissen.
Um sie alle auf einmal umzubenennen, mit Ausnahme der Dateien, die bereits die Erweiterung .html haben (die meisten hatten überhaupt keine), funktionierte dies für mich:
cd wwwroot
find . -xtype f \! -iname *.html -exec mv -iv "{}" "{}.html" \; # batch rename files to append .html suffix IF MISSING
Im Fall des OP könnte ich das leicht ändern, um nur * .txt-Dateien umzubenennen, wie folgt:
find . -xtype f -iname *.txt -exec filename="{}" mv -iv ${filename%.*}.{txt,html} \;
Aufgeschlüsselt (Hammerzeit!):
-iname * .txt
- Bedeutet, dass NUR Dateien berücksichtigt werden, die bereits mit .txt enden
mv -iv "{}. {txt, html}" - Wenn find ein {} als Dateinamen übergibt, extrahiert $ {Dateiname%. *} seinen Basisnamen ohne Erweiterung, um die Parameter für mv zu bilden . bash verwendet {txt, html}, um es als zwei Parameter neu zu schreiben, sodass der letzte Befehl wie folgt ausgeführt wird:mv -iv "filename.txt" "filename.html"
Korrektur erforderlich: Umgang mit Leerzeichen in Dateinamen
Der Befehlmmv
scheint diese Aufgabe für eine große Anzahl von Dateien (Zehntausende in einer Sekunde) sehr effizient auszuführen. Verwenden Sie beispielsweise Folgendes, um alle .xml
Dateien in .html
Dateien umzubenennen :
mmv ";*.xml" "#1#2.html"
Das ;
wird mit dem Pfad übereinstimmen, das *
wird mit dem Dateinamen übereinstimmen, und diese werden als #1
und #2
im Ersatznamen bezeichnet.
Antworten auf exec
oder Pipes waren entweder zu langsam oder schlugen bei einer sehr großen Anzahl von Dateien fehl.
Versuche dies
rename .html .txt *.html
Verwendungszweck:
rename [find] [replace_with] [criteria]
Ein bisschen spät zur Party. Sie könnten es mit xargs tun:
ls *.html | xargs -I {} sh -c 'mv $1 `basename $1 .html`.txt' - {}
Oder wenn sich alle Ihre Dateien in einem Ordner befinden
ls folder/*.html | xargs -I {} sh -c 'mv $1 folder/`basename $1 .html`.txt' - {}
ls
. Dieser Befehl ist lächerlich: Er verwendet nutzlos einen Globus mit ls
, anstatt den Globus direkt zu verwenden. Dies wird mit Dateinamen unterbrochen, die Leerzeichen, Anführungszeichen und (aufgrund fehlender Anführungszeichen) Glob-Zeichen enthalten.
Dies ist eine gute Möglichkeit, mehrere Erweiterungen gleichzeitig zu ändern:
for fname in *.{mp4,avi}
do
mv -v "$fname" "${fname%.???}.mkv"
done
Hinweis: Achten Sie darauf, dass die Erweiterungsgröße gleich ist (die ???)
Wenn Sie PERL bevorzugen, gibt es ein kurzes PERL-Skript (ursprünglich von Larry Wall, dem Erfinder von PERL, geschrieben), das genau das tut, was Sie hier wollen: tips.webdesign10.com/files/rename.pl.txt .
Für Ihr Beispiel sollte Folgendes den Trick tun:
rename.pl 's/html/txt/' *.html
Ähnlich wie zuvor vorgeschlagen, habe ich es so gemacht:
find . -name '*OldText*' -exec sh -c 'mv "$0" "${0/OldText/NewText}"' {} \;
Ich habe zuerst mit validiert
find . -name '*OldText*' -exec sh -c 'echo mv "$0" "${0/OldText/NewText}"' {} \;
Eine Zeile, keine Schleifen:
ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
Beispiel:
$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.json ac8453e2-0d82-4d43-b80e-205edb754700.json
$ ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.txt ac8453e2-0d82-4d43-b80e-205edb754700.txt
Leider ist es nicht trivial, tragbar zu machen. Du brauchst wahrscheinlich ein bisschen Ausdrucksmagie.
for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done
Entfernen Sie das Echo, sobald Sie zufrieden sind, dass es das tut, was Sie wollen.
Bearbeiten: basename
ist für diesen speziellen Fall wahrscheinlich etwas besser lesbar, obwohl expr
es im Allgemeinen flexibler ist.
Hier ist, was ich verwendet habe, um .edge
Dateien umzubenennen.blade.php
for file in *.edge; do mv "$file" "$(basename "$file" .edge).blade.php"; done
Funktioniert wie Charme.
Sie können eine Funktion auch in Bash erstellen, sie hinzufügen .bashrc
oder so und sie dann verwenden, wo immer Sie möchten.
change-ext() {
for file in *.$1; do mv "$file" "$(basename "$file" .$1).$2"; done
}
Verwendungszweck:
change-ext css scss
Quelle des Codes in der Funktion: https://stackoverflow.com/a/1224786/6732111
Benennen Sie die Dateierweiterungen für alle Dateien im aktuellen Verzeichnis und in den Unterverzeichnissen ohne andere Pakete um (verwenden Sie nur das Shell-Skript):
Erstellen Sie ein Shell-Skript rename.sh
im aktuellen Verzeichnis mit dem folgenden Code:
#!/bin/bash
for file in $(find . -name "*$1"); do
mv "$file" "${file%$1}$2"
done
Führen Sie es durch ./rename.sh .old .new
.
Z.B. ./rename.sh .html .txt