Benennen Sie mehrere Dateien mithilfe von Bash-Skripten um

27

Ich möchte mithilfe von Bash-Skripten mehrere Dateien im selben Verzeichnis umbenennen. Die Namen der Dateien lauten wie folgt:

file2602201409853.p
file0901201437404.p  
file0901201438761.p  
file1003201410069.p  
file2602201410180.p

Ich möchte in folgendes Format umbenennen:

file2503201409853.p
file2503201437404.p  
file2503201438761.p  
file2503201410069.p  
file2503201410180.p

Ich habe über den Befehl zum Umbenennen gelesen und versucht, es auf diese Weise zu tun, aber es macht nichts. Ich glaube, ich habe Fragen zur Syntax. Dann habe ich gelesen, dass Sie mit dem Befehl mv wie folgt eine Schleife erstellen können :

for file in cmpsms*2014*.p; do
    mv "$file" "${file/cmpsms*2014*.p/cmpsms25032014*.p}"
done

Ich kann die Dateien aber nicht umbenennen. Was mache ich falsch?

franvergara66
quelle
2
Auf der rechten Seite eines Parametererweiterungsersetzungsausdrucks darf kein Musterausdruck stehen. Was hast du erwartet, wo das *ist?
Kojiro
@ Kiwy Bei dieser Frage geht es darum, einen Teil des Dateinamens zu entfernen. Ergo höchst zweifelhaft duplizieren.
ein Lebenslauf vom
2
Beschreiben Sie bitte das nächste Mal die Änderungen an den Dateinamen, die Sie vornehmen möchten (bevor ich die Unterschiede und Gemeinsamkeiten erkannte, musste ich mir dies eine Weile ansehen). Beispiele sind gut, aber eine Beschreibung sowie Beispiele sind noch besser.
ein Lebenslauf vom

Antworten:

42

Sie haben zu Recht überlegt, zuerst umzubenennen. Die Syntax ist etwas seltsam, wenn Sie nicht an reguläre Ausdrücke gewöhnt sind, aber wenn Sie wissen, was Sie tun, ist dies bei weitem der schnellste / kürzeste Weg:

rename 's/\d{4}/2503/' file*

Das stimmt einfach mit den ersten 4 Zahlen überein und tauscht sie gegen die von Ihnen angegebenen aus.

Und ein Testgeschirr ( -vnbedeutet, dass Sie ausführlich sind, aber nichts tun ), das Ihre Dateinamen verwendet:

$ rename 's/\d{4}/2503/' file* -vn
file0901201437404.p renamed as file2503201437404.p
file0901201438761.p renamed as file2503201438761.p
file1003201410069.p renamed as file2503201410069.p
file2602201409853.p renamed as file2503201409853.p
file2602201410180.p renamed as file2503201410180.p
Oli
quelle
8
Beachten Sie, dass dies die Perl-Umbenennung unter Debian und Derivaten (Ubuntu, Mint,…) ist. Auf anderen Linux-Distributionen gibt renamees ein völlig anderes Tool zum Umbenennen von Dateien (das als Debian ausgeliefert wird rename.ul).
Gilles 'SO - hör auf böse zu sein'
Wenn es in Ihrer Distribution an einem solchen Tool mangelt, lesen Sie die Antwort auf @Michael Campbell. Ich denke, jeder Distributor ersetzt Standard renamewie Debian.
Astery
25

Dies sollte den Trick machen:

for f in file*; do mv $f ${f/${f:4:8}/25032014}; done

Es ersetzt die Zeichenfolge zwischen dem 4. und dem 12. Zeichen durch "25032014".

Chaos
quelle
das for f in file*; do mv $f ${f/${f:4:4}/2503}; donefunktioniert auch.
Avinash Raj
Das ist schön. Wenn Sie nur ein reguläres Wort für Wort ersetzen möchten, funktioniert es wie sed. zBfor f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
Eric
1
@Eric - Ich habe deine Antwort als Alternative gepostet, weil ich denke, dass sie klarer und eleganter ist. Wenn du es auch als Antwort posten willst, lösche ich meins. Vielen Dank!
Yehosef
Warum die fehlenden Anführungszeichen ?
Wildcard
Es gibt mir einen Fehler: "MV: Ziel 'FILE_NAME' ist kein Verzeichnis"
Aubrey
10

Das ist wirklich die Antwort von @ Eric von oben - aber es ist eine elegante Antwort, also poste ich sie als richtige Antwort, um mehr Aufmerksamkeit darauf zu lenken.

for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
Yehosef
quelle
1
ptrn='file[0-9][0-9][0-9][0-9]2014[0-9][0-9][0-9][0-9][0-9].p'
path=/dir
( set -- "${path}/"${ptrn} ; for f ; do {
    echo "mv ${path}/${f} \
        ${path}/file25032014${f#2014}" 
} ; done )

Dies sollte den Trick machen. Hinweis - Ich habe nicht die Angewohnheit, Massenbefehle zu übergeben - wie geschrieben ist es nur ein Echo. Sie müssen das klären, bevor es funktioniert.

mikeserv
quelle
1

Ein einfacher nativer Weg, dies ohne Schleifen zu tun, mit Directory Traversal :

find -type f | xargs -I {} mv {} {}.txt

Jede vorhandene Datei wird umbenannt.

Und unten ein Arbeitsbeispiel mit Parallelisierung :

find -name "file*.p" | parallel 'f="{}" ; mv -- {} ${f:0:4}2503${f:8}'
dtrckd
quelle
Es war ein einfacher erster Ansatz, sich eine bessere Lösung vorzustellen. Wenn Sie einen Arbeitsbefehl möchten, tun Sie
Folgendes
find -type f -name "file*.p" | parallel 'ext="{}" ; mv -- {} ${ext:0:4}2503${ext:8}'
Dtrckd
0

Wenn Sie feststellen, dass Sie so etwas häufig tun, suchen Sie nach "rename.pl". Es ist ein Perl-Skript, aber Sie können es einfach mit Perl-Code füllen (wie z. B. /// Ausdruck), und es führt eine Massenumbenennung basierend auf diesem Ausdruck oder Code durch.

Hier gibt es eine Basisversion: http://stackoverflow.org/wiki/Rename.pl, aber es gibt auch andere Versionen, die im Internet herumfliegen. Es gibt es schon seit Ewigkeiten und Ewigkeiten.

Michael Campbell
quelle