Subtrahieren Sie 1 von allen Dateinamen (benennen Sie sie um) in einem Verzeichnis.

17

Ich habe ein Verzeichnis, das Bilddateien mit Namen wie enthält

image1.jpg 
image2.jpg 
image3.jpg
...

Leider müssen die Bildnamen nullbasiert sein, so image1.jpgsollte es sein image0.jpg, image2.jpgsollte es sein image1.jpgund so weiter.

Ich kann ein Skript schreiben, um MV-Befehle wie diese zu generieren , sie in ein Shell-Skript zu setzen und sie dann auszuführen -

mv image1.jpg image0.jpg
mv image2.jpg image1.jpg
mv image3.jpg image2.jpg
...

Aber ich nehme an, es gibt eine bessere Möglichkeit, dies in Unix zu tun. Also, was ist es?

Wir s
quelle
6
Das ist eigentlich der einfachste Weg, solange es keine Lücken gibt. ( for i in $(seq 0 100); do mv image$[i+1].jpg image$i.jpg; done)
Ricky Beam
5
Ist die Reihenfolge der Bilder wichtig? Wenn nicht, benennen Sie einfach das letzte Bild von imageN.jpgnach um image0.jpgund fertig.
Jnovacho
@jnovacho, ganz schlau! Aber ja, die Reihenfolge der Bilder ist wichtig.
Wes

Antworten:

20

Die gute alte Perl-Umbenennung:

rename 's/(\d+)(\.jpg)/($1-1).$2/e' *

[Bemerkungen]

Die Bildnummern sollten größer als 0 sein.

Wenn die Bilder größer als 9 sind und keine führenden Nullen haben, verwenden Sie diese Option, $(ls -v1 *)um ein Überladen zu vermeiden. Vorgeschlagen von @arielf und bemerkt von @Graeme.

Im Zweifelsfall auch -vfür ausführliche und -nfür Nichthandlungen verwenden.


quelle
Was bedeutet das "e"?
Wes
3
'e' bedeutet auswerten, der Ersetzungsabschnitt wird ausgewertet. siehe auchperlreref
6
Die Dateien sollten in aufsteigender Reihenfolge übergeben werden, um Datenverlust zu vermeiden. Dies funktioniert nur, wenn weniger als 10 Dateien vorhanden sind (oder wenn Zahlen führende Nullen haben).
Graeme
Das ist mir schon aufgefallen, auch da darf ein 0in den Quellen nicht sein .
2
Ersetzen Sie die *am Ende mit `ls -v1 *`und Sie sind sicherer vor Überfällen. Es geht von der niedrigsten zur höchsten Zahl.
Arielf
6

Sie können die generierten mvBefehle an leiten bash. Sie müssen sie also nicht in ein Skript kopieren und ausführen. Sehen:

command_that_generates_mv_commands | bash

Und alles wird ausgeführt, was weitergeleitet wird bash.

Chaos
quelle
Das ist nicht ordentlicher. :)Löst das Problem, also +1.
JMCF125
5

Sie können die Ausgabe iterieren, dies funktioniert für Ihr Beispiel:

i=0 
for file in $(ls *.jpg | sort) ; do 
     mv $file $(echo $file | sed 's/[0-9]*.jpg$/'${i}'.jpg/')
     i=$((++i))
done

Sie müssen sich auf demselben Pfad wie Ihre Dateien befinden

babasbot
quelle
1
Besser zu verwenden -ioder -nmit mv, wird das Überschreiben in Randfällen verhindert.
Graeme
Wäre es nicht sort -Vbesser?
User80551
sortwird nicht funktionieren, es wird sich zeigen, image10.jpgbevor image1.jpgdas ein Problem sein könnte. Du brauchst sort -nk 1.8wie in @ Graemes Antwort.
terdon
@ user80551, sort -Vist eine gute Idee, werde es zu meiner Antwort hinzufügen. Es kann aber auch andere Randfälle geben, nur im Allgemeinen gute Ratschläge, um diese Art von Optionen mit Fragen wie diesen hinzuzufügen, falls jemand kopiert und am Ende Schaden anrichtet.
Graeme
4

Das Folgende scheint für alles zu funktionieren, was zum Muster passt imageNUMBER.jpg. Ich habe echovor den mvBefehl gesetzt, um zuerst zu zeigen, was der Befehl tun würde. Um das Umbenennen tatsächlich durchzuführen, entfernen Sie einfach dieecho

for i in `ls image*.jpg|sort -V` ; do 
    x=`echo $i|sed -e "s/image\(.*\).jpg/\1/"`
    y=$(( $x - 1 ))
    echo mv -i $i image$y.jpg
done

In der ersten Zeile ls image*.jpg|sort -Vwerden die JPG-Dateien mit aufsteigenden Zahlen im Dateinamen aufgelistet. Die x=Zeile extrahiert die Nummer aus dem Dateinamen. Die y=Zeile dekrementiert dann die Zahl um eins. Der eingegebene Dateiname und die yNummer werden dann in dem mvBefehl verwendet, wobei das -iFlag Sie benachrichtigt, bevor eine Datei überschrieben wird.

Für meinen eigenen kleinen Test ergab dies die Ausgabe:

mv -i image1.jpg image0.jpg
mv -i image2.jpg image1.jpg
mv -i image123.jpg image122.jpg

Persönlich würde ich vorschlagen, in einen anderen Dateinamen umzubenennen, da jetzt die Reihenfolge, in der die Dateien verarbeitet werden, einen großen Unterschied machen kann.

brm
quelle
1
Besser zu verwenden -ioder -nmit mv, wird das Überschreiben in Randfällen verhindert.
Graeme
Sehr guter Vorschlag, ich bearbeite die Antwort
brm
In macOS solltest du verwenden sort -n, die -VOption gibt es nicht.
Vincent Sit
4

Für die Verwendung des perlSkripts prename, das zum Umbenennen in Debian-basierten Distributionen verwendet wird, ist ebenfalls GNU find/ erforderlich sort. Die Dateien werden in aufsteigender Reihenfolge abgelegt, um ein Überschreiben zu verhindern.

find . -regex '\./image[0-9]+\.jpg' -print0 | sort -zV |
  xargs -0 rename -n 's/(\d+)\.jpg$/@{[$1-1]}.jpg/'

Entfernen Sie das, -nwenn Sie sicher sind, dass es das tut, was Sie wollen. Warnt vor bereits vorhandenen Dateien. Solange jedoch angezeigt wird, dass die Dateien in aufsteigender Reihenfolge umbenannt werden, gibt es keine Konflikte, wenn sie für real ausgeführt werden.

Graeme
quelle
Datei existiert bereits Probleme mit diesem.
Wes
4

Mit zsh:

autoload zmv # (in ~/.zshrc)
zmv -Qf -n 'image(<->).jpg(n)' 'image$(($1-1)).jpg'

(entfernen, -nwenn Sie glücklich sind).

(n)soll die Liste numerisch sortieren, image9.jpgwird also vorher umbenannt image10.jpg.

Stéphane Chazelas
quelle