web-dev-qa-db-fra.com

Script Linux Shell 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 1.txt ou 1497.txt, etc. Je voudrais renommer tous les fichiers afin que tous les noms de fichiers comportent quatre chiffres.

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

Qu'est-ce qu'un script Shell qui fera cela? Ou une question connexe: comment utiliser grep pour ne faire correspondre que les lignes contenant \d.txt (c'est-à-dire un chiffre, puis un point, puis les lettres txt)?

Voici ce que j'ai jusqu'à présent:

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

Fondamentalement, exécutez cela trois fois, avec des commandes pour trouver un chiffre, deux chiffres et trois noms de fichiers (avec le nombre de zéros initiaux modifié).

53
David Oneill

Essayer:

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

Modifiez le modèle de nom de fichier ([0-9]*.txt) le cas échéant.


Un renommage énuméré à usage général qui ne fait aucune hypothèse sur l'ensemble initial de 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:

48
Colin Hebert

En utilisant le script rename (prename dans certains cas) qui est parfois installé avec Perl, vous pouvez utiliser des expressions Perl pour effectuer le changement de nom. Le script ignore le changement de nom en cas de collision de noms.

La commande ci-dessous renomme uniquement les fichiers de quatre chiffres ou moins suivis d'une extension ".txt". Il ne renomme pas les fichiers qui ne sont pas strictement conformes à ce modèle. Il ne tronque pas les noms composés de 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 les 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, essaieront et échoueront de renommer les fichiers qui ont des espaces dans leurs noms et éventuellement d'autres problèmes.

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

Bon mot:

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

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

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

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 puis exécutez à l'aide de ./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.

4
sinner

Cette version prend également en charge la gestion des chaînes avant (après) le nombre. Mais fondamentalement, vous pouvez faire n'importe quel regex matching + printf tant que votre awk le prend en charge. Et il prend également en charge les espaces (sauf les retours à la ligne) dans les noms de fichiers.

for f in *.txt ;do
    mv "$f" "$( 
        awk -v f="$f" '{
            if ( match(f, /^([a-zA-Z_-]*)([0-9]+)(\..+)/, a)) {
                printf("%s%04d%s", a[1], a[2], a[3])
            } else {
                print(f)
            }
        }' <<<''
    )"
done
1

Pour ne faire correspondre que des fichiers texte à un chiffre, vous pouvez faire ...

$ ls | grep '[0-9]\.txt'
0
LukeN

Indice d'une ligne:

while [ -f ./result/result`printf "%03d" $a`.txt ]; do a=$((a+1));done
RESULT=result/result`printf "%03d" $a`.txt
0
kayn

Pour fournir une solution qui est prudemment écrite pour être correcte même en présence de noms de fichiers avec des espaces:

#!/usr/bin/env bash

pattern='%04d'  # pad with four digits: change this to taste

# enable extglob syntax: +([[:digit:]]) means "one or more digits"
# enable the nullglob flag: If no matches exist, a glob returns nothing (not itself).
shopt -s extglob nullglob

for f in [[:digit:]]*; do               # iterate over filenames that start with digits
  suffix=${f##+([[:digit:]])}           # find the suffix (everything after the last digit)
  number=${f%"$suffix"}                 # find the number (everything before the suffix)
  printf -v new "$pattern" "$number" "$suffix"  # pad the number, then append the suffix
  if [[ $f != "$new" ]]; then                   # if the result differs from the old name
    mv -- "$f" "$new"                           # ...then rename the file.
  fi
done
0
Charles Duffy