Comment zéro pad nombres dans les noms de fichiers en Bash?
Question
Quel est le meilleur moyen, à l'aide de Bash, de renommer des fichiers sous la forme:
(foo1, foo2, ..., foo1300, ..., fooN)
Avec des zéros noms de fichiers:
(foo00001, foo00002, ..., foo01300, ..., fooN)
La solution
En cas N
n'est a priori pas fixe:
for f in foo[0-9]*; do mv $f `printf foo%05d ${f#foo}`; done
Autres conseils
Il n'est pas pur bash, mais beaucoup plus facile avec l' rename
commande:
rename 's/\d+/sprintf("%05d",$&)/e' foo*
J'ai eu un cas plus complexe où les noms de fichier avait un postfix ainsi que d'un préfixe.J'ai également nécessaire d'effectuer une soustraction sur le nombre de nom de fichier.
Pour exemple, j'ai voulu foo56.png
pour devenir foo00000055.png
.
J'espère que cette aide si vous êtes en train de faire quelque chose de plus complexe.
#!/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
Le oneline de commande que j'utilise est ceci:
ls * | cat -n | while read i f; do mv "$f" `printf "PATTERN" "$i"`; done
MOTIF peut être par exemple:
- renommer avec un incrément du compteur:
%04d.${f#*.}
(maintenir l'extension du fichier original) - renommer avec un incrément du compteur avec le préfixe:
photo_%04d.${f#*.}
(garder l'original de l'extension) - renommer avec un incrément du compteur et de changer l'extension des fichiers jpg:
%04d.jpg
- renommer avec un incrément du compteur avec le préfixe et le fichier basename:
photo_$(basename $f .${f#*.})_%04d.${f#*.}
- ...
Vous pouvez filtrer les fichiers à renommer avec par exemple ls *.jpg | ...
Vous avez à disposition la variable f
c'est le nom de fichier et i
c'est le compteur.
Pour votre question, le droit de la commande est:
ls * | cat -n | while read i f; do mv "$f" `printf "foo%d05" "$i"`; done
Pur Bash, pas de processus externe, autre que "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
La suite va le faire:
for ((i=1; i<=N; i++)) ; do mv foo$i `printf foo%05d $i` ; done
EDIT: changé à utiliser ((i=1,...)), merci mweerden!
Voici une solution rapide qui suppose un préfixe de longueur fixe (votre "foo") et de longueur fixe de rembourrage.Si vous avez besoin de plus de souplesse, peut-être que ce sera au moins un point de départ utile.
#!/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
Ma solution remplace les nombres, partout dans une chaîne de caractères
for f in * ; do
number=`echo $f | sed 's/[^0-9]*//g'`
padded=`printf "%04d" $number`
echo $f | sed "s/${number}/${padded}/";
done
Vous pouvez facilement essayer, car il imprime juste transformé les noms de fichiers (pas de système de fichiers sont les opérations réalisées).
Explication:
En parcourant la liste des fichiers
Une boucle: for f in * ; do ;done
, répertorie tous les fichiers et passe chaque nom de fichier $f
variable de corps de boucle.
En saisissant le numéro de chaîne
Avec echo $f | sed
nous tuyau variable $f
pour sed
programme.
Dans la commande sed 's/[^0-9]*//g'
, la partie [^0-9]*
avec le modificateur ^
dit pour correspondre à l'opposé de chiffres de 0 à 9 (pas un nombre) et retirez-la ensuite avec vide de remplacement //
.Pourquoi ne pas simplement supprimer [a-z]
?Parce que le nom de fichier peut contenir des points, des tirets, etc.Donc, nous dépouiller de tout, qui n'est pas un nombre et un nombre.
Ensuite, nous avons affecter le résultat de number
variable.Rappelez-vous de ne pas mettre des espaces dans l'affectation, comme number = …
, parce que vous obtenez un comportement différent.
Nous affecter résultat de l'exécution d'une commande à une variable, emballage de la commande avec backtick de symboles.
Zéro de remplissage
Commande printf "%04d" $number
les changements de format d'un nombre à 4 chiffres et ajoute des zéros si notre numéro contient moins de 4 chiffres.
Remplacement nombre de zéros nombre
Nous utilisons sed
de nouveau avec remplacement de la commande comme s/substring/replacement/
.Pour interpréter nos variables, nous utilisons des guillemets, et remplacer les variables de cette manière ${number}
.
Le script ci-dessus imprime juste transformé noms, alors, faisons-le réel de renommage de l'emploi:
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
Espérons que cela aide quelqu'un.
J'ai passé plusieurs heures à le comprendre.
À gauche de la tablette nombres dans les noms de fichiers:
$ 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
Explication
for f in [0-9]*.[a-z]*; do tmp=`echo $f | \
awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;
- remarque les backticks:
`echo ... $2}\`
(La barre oblique inverse \, immédiatement au-dessus de juste divisions one-liner, sur deux lignes, pour des raisons de lisibilité) - dans une boucle de trouver les fichiers qui sont nommés comme des nombres avec des lettres minuscules extensions:
[0-9]*.[a-z]*
- l'écho de ce nom (
$f
) afin de le transmettre àawk
-F.
:awk
séparateur de champ, une période (.
):s'ils correspondent, sépare les noms de fichiers sous forme de deux champs ($1
= nombre;$2
= extension)- format avec
printf
:imprimer premier champ ($1
, le numéro de la partie) que 4 chiffres (%04d
), puis imprimez la période, puis imprimez-le deuxième champ ($2
:l'extension) comme une chaîne de caractères (%s
).Tout cela est attribué à la$tmp
variable - enfin, déplacez le fichier source (
$f
) pour le nouveau nom de fichier ($tmp
)