web-dev-qa-db-fra.com

Renommer plusieurs fichiers à l'aide de scripts Bash

Je veux renommer plusieurs fichiers dans le même répertoire à l'aide de scripts Bash. Les noms des fichiers sont les suivants:

file2602201409853.p
file0901201437404.p  
file0901201438761.p  
file1003201410069.p  
file2602201410180.p

Je souhaite renommer le format suivant:

file2503201409853.p
file2503201437404.p  
file2503201438761.p  
file2503201410069.p  
file2503201410180.p

Je lisais sur la commande renommer, et j'essaye de le faire de cette façon, mais ça ne fait rien, je pense que j'ai des questions sur la syntaxe. Ensuite, j'ai lu que vous pouvez faire une boucle en utilisant la commande mv comme suit:

for file in cmpsms*2014*.p; do
    mv "$file" "${file/cmpsms*2014*.p/cmpsms25032014*.p}"
done

Mais je ne peux pas renommer les fichiers. Qu'est-ce que je fais mal?

27
franvergara66

Vous aviez raison d'envisager de renommer en premier. La syntaxe est un peu étrange si vous n'êtes pas habitué aux expressions régulières, mais c'est de loin l'itinéraire le plus rapide/le plus court une fois que vous savez ce que vous faites:

rename 's/\d{4}/2503/' file*

Cela correspond simplement aux 4 premiers chiffres et les échange pour ceux que vous avez spécifiés.

Et un harnais de test (-vn signifie être verbeux mais ne pas faire n'importe quoi) en utilisant vos noms de fichiers:

$ rename 's/\d{4}/2503/' file* -vn
file0901201437404.p renamed as file2503201437404.p
file0901201438761.p renamed as file2503201438761.p
file1003201410069.p renamed as file2503201410069.p
file2602201409853.p renamed as file2503201409853.p
file2602201410180.p renamed as file2503201410180.p
42
Oli

Cela devrait faire l'affaire:

for f in file*; do mv $f ${f/${f:4:8}/25032014}; done

Il remplace la chaîne entre le 4ème et le 12ème caractère par "25032014".

25
chaos

c'est vraiment la réponse d'Eric d'en haut - mais c'est une réponse élégante, donc je la republie comme une réponse appropriée pour attirer davantage l'attention dessus.

for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
10
Yehosef

Une manière native simple de le faire sans boucle, avec traversée de répertoire:

find -type f | xargs -I {} mv {} {}.txt

Il renommera chaque fichier en place.

Et ci-dessous un exemple de travail avec parallélisation:

find -name "file*.p" | parallel 'f="{}" ; mv -- {} ${f:0:4}2503${f:8}'
1
dtrckd
ptrn='file[0-9][0-9][0-9][0-9]2014[0-9][0-9][0-9][0-9][0-9].p'
path=/dir
( set -- "${path}/"${ptrn} ; for f ; do {
    echo "mv ${path}/${f} \
        ${path}/file25032014${f#2014}" 
} ; done )

Cela devrait faire l'affaire. Remarque - Je n'ai pas l'habitude de remettre des commandes mv de masse - comme écrit, ce n'est qu'un écho. Vous devrez trier cela avant que cela fonctionne.

1
mikeserv

Si vous constatez que vous faites souvent ce genre de choses, recherchez "rename.pl". C'est un script Perl, mais vous permet simplement de lui donner du code Perl (comme une expression s ///), et il fera un renommage de masse basé sur cette expression ou code.

Il existe une version de base ici: http://stackoverflow.org/wiki/Rename.pl mais il existe d'autres versions flottant sur le net. Il existe depuis des siècles et des âges et des âges.

0
Michael Campbell