Wie kann ich in Bash Zahlen in Dateinamen mit Nullen auffüllen?
Frage
Was ist der beste Weg, mit Bash Dateien im Formular umzubenennen:
(foo1, foo2, ..., foo1300, ..., fooN)
Mit mit Nullen aufgefüllten Dateinamen:
(foo00001, foo00002, ..., foo01300, ..., fooN)
Lösung
Bei N
ist nicht von vornherein festgelegt:
for f in foo[0-9]*; do mv $f `printf foo%05d ${f#foo}`; done
Andere Tipps
Es ist nicht rein bash, aber viel einfacher mit dem rename
Befehl:
rename 's/\d+/sprintf("%05d",$&)/e' foo*
Ich hatte einen komplexen Fall, in dem die Dateinamen als Präfix als auch ein Postfix hatten. Ich brauche auch eine Subtraktion die Anzahl aus dem Dateinamen auszuführen.
Zum Beispiel wollte ich foo56.png
foo00000055.png
werden.
Ich hoffe, das hilft, wenn Sie etwas komplexer tun.
#!/bin/bash
prefix="foo"
postfix=".png"
targetDir="../newframes"
paddingLength=8
for file in ${prefix}[0-9]*${postfix}; do
# strip the prefix off the file name
postfile=${file#$prefix}
# strip the postfix off the file name
number=${postfile%$postfix}
# subtract 1 from the resulting number
i=$((number-1))
# copy to a new name with padded zeros in a new folder
cp ${file} "$targetDir"/$(printf $prefix%0${paddingLength}d$postfix $i)
done
Der oneline Befehl, die ich benutze, ist dies:
ls * | cat -n | while read i f; do mv "$f" `printf "PATTERN" "$i"`; done
Muster können zum Beispiel sein:
- umbenennen mit Zähler erhöhen:
%04d.${f#*.}
(ursprüngliche Dateierweiterung halten) - umbenennen mit Increment-Zähler mit Vorwahl:
photo_%04d.${f#*.}
(ursprüngliche Erweiterung halten) - mit Zähler erhöhen umbenennen und Erweiterung jpg ändern:
%04d.jpg
- umbenennen mit Inkrementzähler mit Präfix und Datei Basisname:
photo_$(basename $f .${f#*.})_%04d.${f#*.}
- ...
Sie können die Datei auswählen, mit zum Beispiel ls *.jpg | ...
umbenennen
Sie haben die Variable f
zur Verfügung, die den Namen und die i
-Datei, die der Zähler ist.
Für Ihre Frage die richtige Befehl lautet:
ls * | cat -n | while read i f; do mv "$f" `printf "foo%d05" "$i"`; done
Reine Bash, keine externen andere Prozesse als 'mv':
for file in foo*; do
newnumber='00000'${file#foo} # get number, pack with zeros
newnumber=${newnumber:(-5)} # the last five characters
mv $file foo$newnumber # rename
done
Im Folgenden wird es tun:
for ((i=1; i<=N; i++)) ; do mv foo$i `printf foo%05d $i` ; done
EDIT: geändert zu verwenden ((i = 1, ...)), dank mweerden
Hier ist eine schnelle Lösung, die eine feste Länge Präfix (Ihre „foo“) und fester Länge Polsterung annimmt. Wenn Sie mehr Flexibilität benötigen, vielleicht zumindest wird dies ein hilfreicher Ausgangspunkt sein.
#!/bin/bash
# some test data
files="foo1
foo2
foo100
foo200
foo9999"
for f in $files; do
prefix=`echo "$f" | cut -c 1-3` # chars 1-3 = "foo"
number=`echo "$f" | cut -c 4-` # chars 4-end = the number
printf "%s%04d\n" "$prefix" "$number"
done
Meine Lösung ersetzt Zahlen, überall in einem String
for f in * ; do
number=`echo $f | sed 's/[^0-9]*//g'`
padded=`printf "%04d" $number`
echo $f | sed "s/${number}/${padded}/";
done
Sie können es leicht versuchen, da es nur die Dateinamen umgewandelt druckt (keine Dateisystemoperationen werden durchgeführt).
Erklärung:
Looping durch Liste der Dateien
Eine Schleife. for f in * ; do ;done
listet alle Dateien und übergibt jeden Dateinamen als $f
Variable Schleifenkörper
Grabbing die Anzahl von Zeichenfolge
Mit echo $f | sed
wir Rohr variable $f
Programm sed
.
Befehl sed 's/[^0-9]*//g'
Teil [^0-9]*
mit Modifikator ^
erzählt von Ziffer 0-9 (keine Zahl) gegenübereinstimmt und es dann mit //
leeren Ersatz zu entfernen. Warum nicht einfach [a-z]
entfernen? Da Dateinamen Punkte enthalten, Bindestriche usw. Also, wir alles abstreifen, dass keine Zahl ist und eine Reihe bekommen.
Als Nächstes weisen wir das Ergebnis Variable number
. Denken Sie daran, nicht zu setzen Räume in Zuordnung, wie number = …
, weil Sie ein anderes Verhalten bekommen.
Wir weisen Ausführungsergebnis eines Befehls Variable, den Befehl mit Graviszeichen Symbole Einwickeln `.
Zero-Padding
Befehl printf "%04d" $number
ändert Format einer Zahl zu 4 Ziffern und fügt Nullen, wenn unsere Zahl kleiner als 4 Ziffern enthält.
Ersetzen Zahl mit Nullen aufgefüllt Zahl
Wir verwenden sed
wieder mit Ersatz-Befehl wie s/substring/replacement/
. Um unsere Variablen zu interpretieren, wir doppelte Anführungszeichen verwenden und unsere Variablen auf diese Weise ${number}
ersetzen.
Das Skript oben gerade druckt Namen umgewandelt, so lassen Sie sich tatsächliche Umbenennung Job:
for f in *.js ; do
number=`echo $f | sed 's/[^0-9]*//g'`
padded=`printf "%04d" $number`
new_name=`echo $f | sed "s/${number}/${padded}/"`
mv $f $new_name;
done
Hoffe, das hilft jemand.
ich mehrere Stunden damit verbracht, um dies herauszufinden.
Um links Pad-Nummern in Dateinamen:
$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 1.zzz
$ for f in [0-9]*.[a-z]*; do tmp=`echo $f | awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;
$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0001.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10
Erklärung
for f in [0-9]*.[a-z]*; do tmp=`echo $f | \
awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;
- beachten Sie die Backticks:
`echo ... $2}\`
(der Backslash, \, unmittelbar über nur teilt, dass Einzeiler über zwei Linien zur besseren Lesbarkeit) - in einer Schleife Dateien, die als Zahlen mit Kleinbuchstaben Erweiterungen benannt sind:
[0-9]*.[a-z]*
- Echo dieser Dateiname (
$f
) es passierenawk
-
-F.
:awk
Feldseparator, eine Periode (.
): wenn angepaßt, trennt die Dateinamen als zwei Felder ($1
= number;$2
= Erweiterung) - Format mit
printf
: print erstes Feld ($1
, die Anzahl Teil) als 4 Ziffern (%04d
), dann wird die Zeit drucken, dann das zweite Feld Druck ($2
: die Erweiterung) als String (%s
). All das mit dem$tmp
Variablen zugewiesen - schließlich bewegen, um die Quelldatei (
$f
) auf den neuen Dateinamen ($tmp
)