it-swarm.com.de

Mehrere Dateien rekursiv finden und in Linux umbenennen

Ich habe Dateien wie a_dbg.txt, b_dbg.txt ... in einem Suse 10-System. Ich möchte ein Bash-Shell-Skript schreiben, das diese Dateien umbenennen soll, indem "_dbg" von ihnen entfernt wird.

Google hat mir vorgeschlagen, den Befehl rename zu verwenden. Also habe ich den Befehl rename _dbg.txt .txt *dbg* auf dem CURRENT_FOLDER ausgeführt.

Mein tatsächlicher CURRENT_FOLDER enthält die folgenden Dateien.

CURRENT_FOLDER/a_dbg.txt
CURRENT_FOLDER/b_dbg.txt
CURRENT_FOLDER/XX/c_dbg.txt
CURRENT_FOLDER/YY/d_dbg.txt

Nachdem Sie den Befehl rename ausgeführt haben, 

CURRENT_FOLDER/a.txt
CURRENT_FOLDER/b.txt
CURRENT_FOLDER/XX/c_dbg.txt
CURRENT_FOLDER/YY/d_dbg.txt

Es ist nicht rekursiv, wie dieser Befehl die Dateien in allen Unterverzeichnissen umbenennt. Wie XX und YY werde ich so viele Unterverzeichnisse haben, deren Name unvorhersehbar ist. Und auch mein CURRENT_FOLDER wird einige andere Dateien haben.

55
rashok

Sie können find verwenden, um alle übereinstimmenden Dateien rekursiv zu finden:

$ find . -iname "*dbg*" -exec rename _dbg.txt .txt '{}' \;

EDIT: was sind der '{}' und \;?

Das Argument -exec bewirkt, dass find für jede gefundene passende Datei rename ausgeführt wird. '{}' wird durch den Pfadnamen der Datei ersetzt. Das letzte Token \; dient nur dazu, das Ende des exec-Ausdrucks zu markieren.

Alles, was auf der Manpage nett zu finden ist, ist:

 -exec utility [argument ...] ;
         True if the program named utility returns a zero value as its
         exit status.  Optional arguments may be passed to the utility.
         The expression must be terminated by a semicolon (``;'').  If you
         invoke find from a Shell you may need to quote the semicolon if
         the Shell would otherwise treat it as a control operator.  If the
         string ``{}'' appears anywhere in the utility name or the argu-
         ments it is replaced by the pathname of the current file.
         Utility will be executed from the directory from which find was
         executed.  Utility and arguments are not subject to the further
         expansion of Shell patterns and constructs.
109
kamituel

mit bash:

shopt -s globstar nullglob
rename _dbg.txt .txt **/*dbg*
11
glenn jackman

kleines Skript, das ich schrieb, um alle Dateien mit der Erweiterung .txt durch die Erweiterung .cpp unter/tmp und die Unterverzeichnisse rekursiv zu ersetzen

#!/bin/bash

for file in $(find /tmp -name '*.txt')
do
  mv $file $(echo "$file" | sed -r 's|.txt|.cpp|g')
done
11
VishnuVardhanA

Um rekursiv umzubenennen, verwende ich folgende Befehle:

find -iname \*.* | rename -v "s/ /-/g"
11
Gantan

Das obige Skript kann in einer Zeile geschrieben werden:

find /tmp -name "*.txt" -exec bash -c 'mv $0 $(echo "$0" | sed -r \"s|.txt|.cpp|g\")' '{}' \;
2
Manh Tai

Dateien und Verzeichnisse mit find -execdir | rename umbenennen

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

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

Im Gegensatz zu -execdir führt die Option awesome -exec eine cd in das Verzeichnis ein, bevor sie den Befehl rename ausführt.

-depth muss sicherstellen, dass die Umbenennung zuerst bei Kindern und dann bei Eltern erfolgt, um mögliche Probleme mit fehlenden übergeordneten Verzeichnissen zu vermeiden.

-execdir ist erforderlich, da das Umbenennen nicht für Eingabepfade außerhalb des Dateinamens geeignet ist, z. Folgendes schlägt fehl:

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

Das PATH-Hacking ist erforderlich, da -execdir einen sehr ärgerlichen Nachteil hat: find ist äußerst meinungsstark und weigert sich, etwas mit -execdir zu tun, wenn Sie relative Pfade in Ihrer PATH-Umgebungsvariablen haben, z. ./node_modules/.bin, fehlgeschlagen mit:

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: https://askubuntu.com/questions/621132/why-using-the-execdir-action-is-insecure-for-directory-which-is-in-the-path/1109378#1109378

-execdir ist ein GNU find Erweiterung zu POSIX . rename basiert auf Perl und stammt aus dem rename-Paket. Getestet in Ubuntu 18.10.

Lookahead Workaround umbenennen

Wenn Ihre Eingabepfade nicht aus find stammen oder wenn Sie genug von den relativen Pfadstörungen gehabt haben, können wir ein Perl-Lookahead verwenden, um Verzeichnisse sicher wie folgt umzubenennen:

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

Ich habe kein praktisches Analogon für -execdir mit xargs gefunden: https://superuser.com/questions/893890/xargs-change-working-directory-to-file-path-vor-executing/915686

Der sort -r ist erforderlich, um sicherzustellen, dass Dateien hinter ihren jeweiligen Verzeichnissen kommen, da längere Pfade nach kürzeren Pfaden mit demselben Präfix kommen. 

Sie können dies unten verwenden.

rename --no-act 's/\.html$/\.php/' *.html */*.html
0
井上智文

Wenn Sie nur umbenennen möchten und ein externes Tool verwenden, können Sie rnm verwenden. Der Befehl wäre:

#on current folder
rnm -dp -1 -fo -ssf '_dbg' -rs '/_dbg//' *

-dp -1 macht es für alle Unterverzeichnisse rekursiv.

-fo impliziert den Modus "Nur Datei".

-ssf '_dbg' sucht nach Dateien mit _dbg im Dateinamen.

-rs '/_dbg//' ersetzt _dbg durch eine leere Zeichenfolge.

Sie können den obigen Befehl auch mit dem Pfad des CURRENT_FOLDER ausführen:

rnm -dp -1 -fo -ssf '_dbg' -rs '/_dbg//' /path/to/the/directory
0
Jahid