Finden Sie mehrere Dateien, und benennen Sie Sie in Linux
Ich habe Dateien wie a_dbg.txt, b_dbg.txt ...
im Suse 10
system. Ich möchte schreiben Sie ein bash-shell-Skript, das sollten benennen Sie diese Dateien entfernen "_dbg" von Ihnen.
Google mir vorgeschlagen zu verwenden rename
Befehl. Also habe ich den Befehl ausgeführt rename _dbg.txt .txt *dbg*
auf die CURRENT_FOLDER
Meine eigentliche CURRENT_FOLDER
enthält die untenstehenden Dateien.
CURRENT_FOLDER/a_dbg.txt
CURRENT_FOLDER/b_dbg.txt
CURRENT_FOLDER/XX/c_dbg.txt
CURRENT_FOLDER/YY/d_dbg.txt
Nach Ausführung der rename
Befehl,
CURRENT_FOLDER/a.txt
CURRENT_FOLDER/b.txt
CURRENT_FOLDER/XX/c_dbg.txt
CURRENT_FOLDER/YY/d_dbg.txt
Ihre nicht tun rekursiv, wie man diesen Befehl zum umbenennen von Dateien in allen Unterverzeichnissen. Wie XX
und YY
ich werde so viele Unterverzeichnisse, die den Namen nicht vorhersagbar ist. Und auch meine CURRENT_FOLDER
werden, einige andere Dateien auch.
- Ich bekomme
Bareword "..." not allowed while "strict subs" in use at (eval 1) line 1.
- Warum nicht EINFACH umbenennen -r existieren und uns das Leben erleichtern, statt der sperrigen workarounds?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie
find
finden Sie alle passenden Dateien rekursiv:EDIT: was die
'{}'
und\;
sind?Den
-exec
argument finden, führenrename
für jede passende Datei gefunden.'{}'
wird ersetzt durch den Pfad-Namen der Datei. Das Letzte token,\;
es ist nur zu markieren das Ende des exec Ausdruck.Alles schön beschrieben auf der man-Seite zu finden:
find . -type f "*dbg*" -exec rename "_dbg.txt" ".txt" * {} \;
Illegal octal digit '9' at (user-supplied code), at end of line
. Ich habe versucht, sowohl einfache Anführungszeichen, doppelte Anführungszeichen und keine Anführungszeichen für die Argumente derrename
. Speziell bin ich versucht zu ersetzen0123-MISC
mit0123_AB_MISC
. dies ist mein Befehlfind . -iname "*0123-MISC*" -exec rename 0123-MISC 0123_AB_MISC {} \;
0
werden interpretiert als oktal-Ziffern von perl, die Skriptsprache verwendet, die vonrename
. In diesem Fall musste ich für die Lösung von @glennBareword "..." not allowed while "strict subs" in use at ...
versuchen:find . -iname "*BUILD*" -exec rename 's/_dbg.txt/.txt/' '{}' \;
find . -iname ".htaccess" -exec rename .htaccess .htaccess_disabled '{}' \;
Und wiederherstellen:find . -iname ".htaccess_disabled" -exec rename .htaccess_disabled .htaccess '{}' \;
kleinen Skript, das ich schrieb, um zu ersetzen Sie alle Dateien, die mit .txt-Erweiterung .cpp-Erweiterung unter /tmp " und " Unterverzeichnisse rekursiv
for file in $(find ...)
. Siehe Warum sollten Sie nicht Parsen der Ausgabe von ls(1).Umbenennung rekursiv ich die folgenden Befehle verwenden:
find -iname \*.* | rename -v -f "s/\.bak//g"
rename
versucht, benennen Sie den gesamten Pfad und schlägt fehl, wenn ein übergeordnetes Verzeichnis geändert werden. Stattdessen müssen Sie arbeiten auf Basisnamen nur wie gezeigt bei: stackoverflow.com/questions/16541582/..., und fahren Sie Tiefe zuerst mit-depth
.mit bash:
shopt -s globstar nullstar
. Für das umbenennen-tool, das installiert wird, überbrew install rename
auf MacOS, die ich zu tun hatterename -s oldStuff newStuff **/*
Scipt oben erwähnt sind, können in eine Zeile geschrieben werden:
find -execdir rename
zum umbenennen von Dateien und Verzeichnissen, die mit einem regulären AusdruckWenn Sie benennen Sie die beiden Dateien und Verzeichnissen mit regulären Ausdrücken, und nicht einfach mit einem suffix, dann ist das ein gutes Muster:
GitHub upstream.
Beispiel für die Verwendung zu ersetzen Leerzeichen '' mit Bindestrich '-'. Testlauf:
Tun, die Sie ersetzen:
Den genial
-execdir
option hat einecd
in das Verzeichnis vor dem ausführen derrename
Befehl, im Gegensatz zu-exec
.-depth
sicherzustellen, dass die Umbenennung geschieht zunächst über die Kinder, dann die Eltern, um zu verhindern, dass potenzielle Probleme mit der fehlenden übergeordneten Verzeichnisse.-execdir
ist erforderlich, da umbenennen nicht gut spielen mit nicht-basename-Eingang Pfade, z.B. den folgenden fehl:Den
PATH
hacking ist erforderlich, da-execdir
hat einen sehr lästigen Nachteil:find
ist extrem rechthaberisch und weigert sich, etwas zu tun mit-execdir
wenn Sie relative Pfade in IhrerPATH
Umgebungsvariable, z.B../node_modules/.bin
andernfalls mit: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-finden Erweiterung von POSIX.rename
ist Perl-basiert und kommt aus derrename
Paket.Umbenennen lookahead Abhilfe
Wenn Sie Ihre Eingabe Pfade kommen nicht aus
find
, oder wenn Sie habe genug von den relativen Pfad ärger, wir können einige Perl-lookahead sicher Verzeichnisse umbenennen in:Habe ich nicht gefunden eine bequeme Analog für
-execdir
mitxargs
: https://superuser.com/questions/893890/xargs-change-working-directory-to-file-path-before-executing/915686Den
sort -r
ist erforderlich, um sicherzustellen, dass die Dateien kommen nach Ihren jeweiligen Verzeichnissen, da längere Wege nach kürzeren diejenigen, die mit dem gleichen Präfix.Getestet in Ubuntu 18.10.
Wenn Sie wollen einfach nur umbenennen und nicht dagegen, mit einem externen tool, dann können Sie rnm. Wäre der Befehl:
-dp -1
wird es rekursiv auf alle Unterverzeichnisse.-fo
impliziert Datei-only-Modus.-ssf '_dbg'
sucht nach Dateien mit _dbg in den Dateinamen.-rs '/_dbg//'
ersetzt _dbg mit einem leeren string.Führen Sie den obigen Befehl mit dem Pfad des CURRENT_FOLDER zu:
Können Sie dies weiter unten.
klassische Lösung:
~/tmp$ mkdir a && cd a/ && touch 1_dbg.txt && cd ..
~/tmp$ for f in $(find . -name "*dbg*"); do mv $f $(echo $f | sed 's/_dbg//'); done
~/tmp$ cd a/ ~/tmp/a$ l total 8 drwxrwxr-x 2 repu1sion repu1sion 4096 Sep 17 21:17 . drwxrwxr-x 3 repu1sion repu1sion 4096 Sep 17 21:17 .. -rw-rw-r-- 1 repu1sion repu1sion 0 Sep 17 21:17 1.txt
for f in $(find ....)
: tun Sie das nicht! es bricht mit Dateinamen, die Leerzeichen oder glob-Zeichen; außerdemfind
hat die-exec
option, dass sehr wahrscheinlich stattdessen verwendet werden; oderfor f in *_dbg*; do
oder wenn Sie möchten, eine rekursive glob,for f in **/*_dbg; do
mitshopt -s globstar
.mv $f ...
: Anführungszeichen fehlt (sonst bricht es mit Dateinamen, die Leerzeichen oder glob-Zeichen). Verwendenmv "$f" ...
stattdessen, oder noch bessermf -- "$f" ...
.echo $f | sed 's/_dbg//'
: diese Regel zeigt eine mangelnde Kenntnis der parameter-Erweiterungen Funktionen der shell (neben den fehlenden Anführungszeichen in derecho $f
- Anweisung). Betrachten Sie stattdessenecho "${f/_dbg}"
.shopt -s globstar nullglob; for f in **/*_dbg*; do mv -- "$f" "${f/_dbg}"; done
.find . -regex "*dbg*"
; do mv -v $f $(echo $f | sed "s/_dbg//") ; done