Benennen Sie Dateien unter Linux rekursiv um (Erweiterung ändern)

22

Wie benenne ich alle Dateien in einem Verzeichnis rekursiv um und ändere eine Dateierweiterung in eine andere für Tausende von Dateien in Tausenden von Unterordnern? Ich sehe viele Befehle, die fast das tun, was ich will, aber nicht ganz.

find . -name "*.andnav" -exec rename .andnav .tile {} \;
syntax error at (eval 1) line 1, near "."

...

rename -nv 's/\.andnav$/\.tile/i' *.andnav
0.png.andnav renamed as 0.png.tile
Endolith
quelle
1
Haben Sie Debian renameoder Red Hat rename?
Ignacio Vazquez-Abrams
@Ignacio: Ubuntu = Debian?
Endolith
Ja, Ubuntu ist ein Debian-Derivat.
Ignacio Vazquez-Abrams

Antworten:

23

Herausgefunden

find . -name "*.andnav" -exec rename -v 's/\.andnav$/\.tile/i' {} \;
./0/0.png.andnav renamed as ./0/0.png.tile
./0/1.png.andnav renamed as ./0/1.png.tile
./1/0.png.andnav renamed as ./1/0.png.tile
./1/1.png.andnav renamed as ./1/1.png.tile

Natürlich entfernen Sie das -v, wenn Sie es tatsächlich tun, oder es wird Zeit verschwenden, alle Dateien anzuzeigen

Endolith
quelle
14

So etwas wie:

find . -name '*.andnav' -exec sh -c 'mv "$0" "${0%.andnav}.tile"' {} \;
cYrus
quelle
Dieser funktionierte am besten für mich
CWD
14

Mit zsh:

autoload zmv
zmv -n '(**/)(*).andnav' '$1$2.tile'

Entfernen Sie das -n, um die Umbenennung tatsächlich durchzuführen.

Gilles 'SO - hör auf böse zu sein'
quelle
1
Fantastische Antwort!
Chris Knadler
4

Ich fand diese Methode einfacher und leichter zu lesen:

find . -name "*.andnav" | rename "s/\.andnav$/.tile/"

Zumindest bei Ubuntu-Ableitungen übernimmt Umbenennen eine Liste von Dateien aus STDIN, wenn sich keine in der Befehlszeile befinden. Und das kann einfach getestet werden mit:

find . -name "*.andnav" | rename -vn "s/\.andnav$/.tile/"

bis Sie es richtig machen.

Bernd Wechner
quelle
1

Benennen Sie Dateien und Verzeichnisse mit find -execdir | rename

Wenn Sie Dateien und Verzeichnisse nicht einfach mit einem Suffix umbenennen, ist dies ein gutes Muster:

PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
  find . -depth -execdir rename 's/findme/replaceme/' '{}' \;

Anders -execdirals cdbei der Option " awesome " wird vor dem Ausführen des renameBefehls ein Eintrag in das Verzeichnis erstellt -exec.

-depth Stellen Sie sicher, dass die Umbenennung zuerst bei Kindern und dann bei Eltern erfolgt, um potenzielle Probleme mit fehlenden Elternverzeichnissen zu vermeiden.

-execdir ist erforderlich, weil das Umbenennen bei Eingabepfaden ohne Basisnamen nicht gut funktioniert, z. B. schlägt Folgendes fehl:

rename 's/findme/replaceme/g' acc/acc

Das PATHHacken ist erforderlich, da -execdires einen sehr ärgerlichen Nachteil hat: Es findist äußerst kritisch und weigert sich, irgendetwas damit zu tun, -execdirwenn Sie relative Pfade in Ihrer PATHUmgebungsvariablen haben, z ./node_modules/.bin.

find: Der relative Pfad './node_modules/.bin' ist in der Umgebungsvariablen PATH enthalten, die in Kombination mit der Aktion -execdir von find unsicher ist. Bitte entfernen Sie diesen Eintrag aus $ PATH

Siehe auch: /ubuntu/621132/why-using-the-execdir-action-is-insecure-for-directory-which-is-in-the-path/1109378#1109378

-execdirist eine GNU find Erweiterung zu POSIX . renameist Perl-basiert und stammt aus dem renamePaket. Getestet in Ubuntu 18.10.

Benennen Sie die Lookahead-Problemumgehung um

Wenn Ihre Eingabepfade nicht von stammen findoder wenn Sie genug von der relativen Pfadbelästigung haben, können wir einige Perl-Lookaheads verwenden, um Verzeichnisse sicher umzubenennen, wie in:

git ls-files | sort -r | xargs rename 's/findme(?!.*\/)\/?$/replaceme/g' '{}'

Ich habe keine passende Entsprechung für -execdirmit gefunden xargs: Xargs: Arbeitsverzeichnis vor der Ausführung in Dateipfad ändern?

Das sort -rist erforderlich, um sicherzustellen, dass Dateien nach ihren jeweiligen Verzeichnissen kommen, da längere Pfade nach kürzeren mit demselben Präfix kommen.

Ciro Santilli ist ein Schauspieler
quelle