
Ich habe ein Verzeichnis mit Unterverzeichnissen, die viele Dateien mit dem Namen enthalten:
file1.tif
file2.tif
file3.tif
file4.tif
file5.tif
file6.tif
file7.tif...
Ich möchte ein „Cycling“-Suffix und hinzufügen c1
, um die Dateinamen zu erhalten:c2
c3
file1c1.tif
file2c2.tif
file3c3.tif
file4c1.tif
file5c2.tif
file6c3.tif
file7c1.tif...
Und dies in allen Unterverzeichnissen des obersten Verzeichnisses.
Aber ich kann nicht herausfinden, wie das geht.
Ist das möglich? Wie?
Antwort1
Mit find
+ dem Perl-basierten prename
(auch bekannt rename
als einige frühere Ubuntus) konnte man die Ziffernfolge vor einem Literal abgleichen .
und sie dann im gewünschten Format schreiben, beispielsweise mit Modulo-Division
find . -name '*.tif' -execdir prename -vn -- 's/(\d+)\./sprintf "%dc%d.", $1, ($1-1)%3+1/e' {} +
(Mit den -vn
Flags können Sie einen „Trockenlauf“ durchführen, um zu sehen, wie die Dateien umbenannt würden, bevor Sie sie festschreiben.)
Beispiel gegeben
$ tree
.
├── bar
│ ├── file1.tif
│ ├── file2.tif
│ ├── file3.tif
│ ├── file4.tif
│ ├── file5.tif
│ ├── file6.tif
│ └── file7.tif
├── foo
│ ├── egg
│ │ ├── file1.tif
│ │ └── file2.tif
│ ├── file1.tif
│ ├── file2.tif
│ └── file3.tif
└── spam
├── file1.tif
└── file2.tif
4 directories, 14 files
Dann
find . -name '*.tif' -execdir prename -- 's/(\d+)\./sprintf "%dc%d.", $1, ($1-1)%3+1/e' {} +
führt zu
$ tree
.
├── bar
│ ├── file1c1.tif
│ ├── file2c2.tif
│ ├── file3c3.tif
│ ├── file4c1.tif
│ ├── file5c2.tif
│ ├── file6c3.tif
│ └── file7c1.tif
├── foo
│ ├── egg
│ │ ├── file1c1.tif
│ │ └── file2c2.tif
│ ├── file1c1.tif
│ ├── file2c2.tif
│ └── file3c3.tif
└── spam
├── file1c1.tif
└── file2c2.tif
4 directories, 14 files
Antwort2
Bearbeitung basierend auf Kommentar:
Wenn Sie den Zähler durchlaufen lassen möchten, d. h. <number>
zwischen c<number>
1 und 3 wechseln möchten:
Probelauf:
shopt -s globstar
for d in **/*/; do
( cd "$d" && pwd && count=1 && shopt -s nullglob && for f in file*.tif; do
echo mv -i "$f" "${f%.tif}"c${count}.tif
if ((count=3)); then
count=1
else
((count++))
fi
done )
done
Aktion:
shopt -s globstar
for d in **/*/; do
( cd "$d" && count=1 && shopt -s nullglob && for f in file*.tif; do
mv -i "$f" "${f%.tif}"c${count}.tif
if ((count=3)); then
count=1
else
((count++))
fi
done )
done
Beispiel:
$ tree
.
├── bar
│ ├── file1.tif
│ ├── file2.tif
│ ├── file3.tif
│ └── file4.tif
├── foo
│ ├── egg
│ │ ├── file1.tif
│ │ └── file2.tif
│ ├── file1.tif
│ ├── file2.tif
│ └── file3.tif
└── spam
├── file1.tif
└── file2.tif
$ shopt -s globstar
$ for d in **/*/; do ( cd "$d" && pwd && count=1 && shopt -s nullglob && for f in file*.tif; do \
echo mv -i "$f" "${f%.tif}"c${count}.tif; if ((count=3)); then count=1; else ((count++)); fi; done ); done
/home/foobar/bar
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
mv -i file3.tif file3c3.tif
mv -i file4.tif file4c1.tif
/home/foobar/foo
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
mv -i file3.tif file3c3.tif
/home/foobar/foo/egg
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
/home/foobar/spam
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
$ for d in **/*/; do ( cd "$d" && count=1 && shopt -s nullglob && for f in file*.tif; do \
mv -i "$f" "${f%.tif}"c${count}.tif; if ((count=3)); then count=1; else ((count++)); fi; done ); done
$ tree
.
├── bar
│ ├── file1c1.tif
│ ├── file2c2.tif
│ ├── file3c3.tif
│ └── file4c1.tif
├── foo
│ ├── egg
│ │ ├── file1c1.tif
│ │ └── file2c2.tif
│ ├── file1c1.tif
│ ├── file2c2.tif
│ └── file3c3.tif
└── spam
├── file1c1.tif
└── file2c2.tif
Ursprüngliche Antwort:
Mit bash
:
shopt -s globstar
for d in **/*/; do ( cd "$d" && pwd && count=1 && shopt -s nullglob \
&& for f in file*.tif; do echo mv -i "$f" "${f%.tif}"c${count}.tif; \
((count++)); done ); done
Hier durchlaufen wir die Verzeichnisnamen,
globstar
die Shell-Option ermöglicht es uns, das Verzeichnis rekursiv zu durchlaufenDer Teil darin
()
läuft in einer Unterschale, um zu verhindern, dass ercd
in der aktuellen Schale geändert wird.Wir
cd
durchsuchen die Verzeichnisse, finden diefile*.tif
Dateien und benennen sie nach Bedarf umcount
beim Umbenennen für jede Datei einen inkrementierenden Zähler führen
Das Obige ist ein Probedurchlauf und zeigt Ihnen das Verzeichnis, in dem die Umbenennung vorgenommen wird, und welcher mv
Befehl ausgeführt wird. Wenn Sie zufrieden sind, führen Sie Folgendes aus:
shopt -s globstar
for d in **/*/; do ( cd "$d" && count=1 && shopt -s nullglob && \
for f in file*.tif; do mv -i "$f" "${f%.tif}"c${count}.tif; ((count++)); done ); done
Es gibt einen Vorbehalt, da die Shell eine lexikalische Sortierung durchführt, sodass Dateien z. B. file10.tif
früher umbenannt werden als file2.tif
. Wenn Sie das nicht möchten, sortieren Sie vor dem Umbenennen oder verwenden Sie die Option zsh
mit numericglobsort
.
Antwort3
Dank heemayl hat sich alles geklärt. Wir mussten die angegebene Zyklus-Inkrement-Schleife ein wenig modifizieren, da sie bei uns nicht funktionierte. Wir haben: if ((count=3)) in: if (("$count"==3)) geändert. Der endgültige Code, den wir jetzt erfolgreich verwenden, ist:
shopt -s globstar
for d in **/*/; do
( cd "$d" && count=1 && shopt -s nullglob && for f in *.tif; do
echo mv -i "$f" "${f%.tif}"c${count}.tif
if (("$count"==3)); then
count=1
else
((count++))
fi
done )
done
Nochmals vielen Dank an heemayl für seine/ihre Hilfe und Geduld …