61 votes

Shell Linux script pour ajouter des zéros de tête aux noms de fichiers

J'ai un dossier contenant environ 1 700 fichiers. Ils sont tous nommés comme suit 1.txt o 1497.txt etc. Je voudrais renommer tous les fichiers de manière à ce que tous les noms de fichiers aient une longueur de quatre chiffres.

C'est-à-dire, 23.txt devient 0023.txt .

Quel est un script qui fera cela ? Ou une question connexe : Comment puis-je utiliser grep pour ne faire correspondre que les lignes qui contiennent \d.txt (c'est à dire un chiffre, puis un point, puis les lettres txt ) ?

Voici ce que j'ai pour l'instant :

for a in [command i need help with]
do
  mv $a 000$a
done

En gros, exécutez cette commande trois fois, avec des commandes pour trouver des noms de fichiers à un, deux et trois chiffres (en modifiant le nombre de zéros initiaux).

0 votes

1 votes

@CiroSantilli, d'ailleurs, j'ai récemment eu quelqu'un qui s'est opposé à ce qu'un dupe soit fermé avec cela, car la logique de remplissage des premiers chiffres et la logique de remplissage des chiffres plus tard dans un nom diffèrent quelque peu. (Par conséquent, stackoverflow.com/questions/46993470/ est actuellement signalé comme étant une copie de cette réponse, et no une copie de celui-ci).

54voto

Colin Hebert Points 40084

Essayez :

for a in [0-9]*.txt; do
    mv $a `printf %04d.%s ${a%.*} ${a##*.}`
done

Modifier le modèle de nom de fichier ( [0-9]*.txt ) si nécessaire.


Un renommage énuméré à usage général qui ne fait aucune hypothèse sur l'ensemble initial des noms de fichiers :

X=1;
for i in *.txt; do
  mv $i $(printf %04d.%s ${X%.*} ${i##*.})
  let X="$X+1"
done

Sur le même sujet :

0 votes

Cela produit un tas d'erreurs pour chaque nom de fichier qui a déjà 4 chiffres. L'ajout de foo au début permettrait de contourner ce problème, mais je ne voulais pas que ce soit là. Merci pour ces liens.

1 votes

Votre solution n'est pas robuste. Si un fichier d'entrée est nommé 050.txt il sera renommé en 0040.txt . Pourquoi ? Parce qu'en C 050 est une constante octale dont la valeur est 40 !

0 votes

@AntoineMathys : bien vu ! !! Pire, la répétition de la commande renomme ce fichier, à nouveau, à chaque exécution.

17voto

Dennis Williamson Points 105818

Utilisation de la rename ( prename dans certains cas) script qui est parfois installé avec Perl, vous pouvez utiliser des expressions Perl pour effectuer le renommage. Le script saute le renommage s'il y a une collision de noms.

La commande ci-dessous renomme uniquement les fichiers qui ont quatre chiffres ou moins suivis d'une extension ".txt". Elle ne renomme pas les fichiers qui ne sont pas strictement conformes à ce modèle. Elle ne tronque pas les noms qui comportent plus de quatre chiffres.

rename 'unless (/0+[0-9]{4}.txt/) {s/^([0-9]{1,3}\.txt)$/000$1/g;s/0*([0-9]{4}\..*)/$1/}' *

Quelques exemples :

Original    Becomes
1.txt       0001.txt
02.txt      0002.txt
123.txt     0123.txt
00000.txt   00000.txt
1.23.txt    1.23.txt

Les autres réponses données jusqu'à présent tenteront de renommer des fichiers qui ne sont pas conformes au modèle, produiront des erreurs pour les noms de fichiers qui contiennent des caractères non numériques, effectueront des renommages qui produisent des collisions de noms, tenteront et échoueront à renommer des fichiers qui ont des espaces dans leurs noms et éventuellement d'autres problèmes.

0 votes

Yagni. Sérieusement. Qui se soucie des noms de fichiers qui contiennent des espaces ou des caractères non numériques si ce n'est pas dans le cadre de la question ? Si le PO voulait écrire un script d'usage général, il l'aurait dit dans la question, et les réponses auraient été adaptées en conséquence.

17 votes

@Chris : Mes réponses font souvent deux choses. D'abord, elles tentent de répondre à la question du PO. Deuxièmement, elles tentent de fournir des informations supplémentaires qui pourraient être utiles aux futurs utilisateurs de la question.

2 votes

@Dennis : Merci d'avoir fourni cette réponse, la réponse la mieux notée n'a pas résolu mon problème particulier mais comme vous l'avez noté, vous avez fourni une réponse plus générale et plus large qui a aidé. Merci.

14voto

Chris Jester-Young Points 102876
for a in *.txt; do
  b=$(printf %04d.txt ${a%.txt})
  if [ $a != $b ]; then
    mv $a $b
  fi
done

0 votes

Merci pour la réponse ! En gros, c'est la même chose que l'autre qui est arrivée exactement au même moment.

0 votes

Ne provoque pas d'erreurs si les noms de fichiers d'entrée ne comportent pas d'espaces. Il faudrait probablement ajouter plus de guillemets pour éviter cela :)

9voto

rkhayrov Points 5829

Un seul mot :

ls | awk '/^([0-9]+)\.txt$/ { printf("%s %04d.txt\n", $0, $1) }' | xargs -n2 mv

Comment puis-je utiliser grep pour ne faire correspondre que les lignes qui contiennent \d.txt (IE 1 chiffre, puis un point, puis les lettres txt) ?

grep -E '^[0-9]\.txt$'

6voto

sinbag Points 355

Supposons que vous ayez des fichiers avec le type de données .dat dans votre dossier. Copiez simplement ce code dans un fichier nommé run.sh, rendez-le exécutable en exécutant chmode +x run.sh et ensuite l'exécuter en utilisant ./run.sh :

#!/bin/bash
num=0
for i in *.dat
do

  a=`printf "%05d" $num`
  mv "$i" "filename_$a.dat"
  let "num = $(($num + 1))"
done

Cela convertira tous les fichiers de votre dossier en filename_00000.dat , filename_00001.dat etc.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X