2010-08-12 21 views
2

J'ai un grand nombre de fichiers image que je dois renommer depuis la ligne de commande. Je crois que la meilleure façon de le faire est d'utiliser awk (veuillez corriger si c'est incorrect).Renommer des fichiers en utilisant UNIX - devrais-je utiliser awk?

noms de fichiers sont comme le

suivant
1038282829128738912-1.jpg 

Chaque fichier image commence par « 103 » et je veux remplacer cette partie du nom de fichier avec « 201003 » - en laissant le reste intact ... par exemple.

2010038282829128738912-1.jpg 

Les images sont dans plusieurs dossiers sous un dossier principal (images) - mais il serait à portée de main pour toutes les images à copier dans un dossier (images_renamed)

Je ne sais pas où commencer par cela - et j'ai googlé pour l'utilisation awk, mais ne peut trouver des exemples de renommer le texte à l'intérieur fichiers.

Toute aide appréciée. Merci/

+0

Le script Perl 'rename' fait ce travail haut la main. En effet, l'une des motivations pour écrire Perl était le support limité d'awk pour de nombreux fichiers. 'renommer 'devrait déjà faire partie des distributions basées sur Debian ou http://search.cpan.org/~rmbarker/File-Rename-0.05/ – msw

+0

Merci pour toutes vos réponses - Je vais faire quelques lectures et essayer de ceux-ci. Je reviendrai plus tard et je répondrai à la question - je suis sûr qu'il doit y avoir des réponses correctes ici :-) merci encore. – calumbrodie

+0

vérifier ici: http: //theunixshell.blogspot.com/2013/01/bulk-renaming-of-files-in-unix.html – Vijay

Répondre

6

Si vous avez la commande rename sur votre UNIX, vous devriez être en mesure d'utiliser quelque chose comme:

mkdir images_renamed 
cd images_renamed 
cp ../103*.jpg . 
rename 103 201003 *.jpg 

Le rename FROM TO FILE renommera tous les fichiers spécifiés par FILE, en changeant la première occurrence de FROM à TO.

Si ce n'est pas disponible, vous pouvez utiliser quelque chose comme:

mkdir images_renamed 
for fspec in 103*.jpg ; do 
    cp ${fspec} images_renamed/201003${fspec:3} 
done 

Pour ce faire récursive, je le mettrais dans un script avec find:

#!/usr/bin/bash 

rm -rf images_renamed 
ls -lR images 
echo 

cd images 
find . -name '*.jpg' | while read -r; do 
    mkdir -p "../images_renamed/$(dirname "$REPLY")" 
    echo 'Copying from' [$REPLY] 
    echo '   to' [../images_renamed/$REPLY] and renaming. 
    echo 
    cp "$REPLY" "../images_renamed/$REPLY" 
    cd "$(dirname "../images_renamed/$REPLY")" 
    rename 103 201003 "$(basename "$REPLY")" 
    cd - >/dev/null 
done 

cd .. 
ls -lR images_renamed 

Seul le bit milieu de cette est nécessaire, le reste est pour les tests. La sortie ci-dessous montre comment cela fonctionne, en copiant tous les fichiers dans la nouvelle structure de répertoires et en renommant les fichiers pertinents.

images: 
total 0 
drwxr-xr-x+ 1 pax None 0 2010-08-12 20:55 dir1 
drwxr-xr-x+ 1 pax None 0 2010-08-12 20:55 dir2 
drwxr-xr-x+ 1 pax None 0 2010-08-12 20:56 dir3 

images/dir1: 
total 0 
-rw-r--r-- 1 pax None 0 2010-08-12 20:55 102xxx.jpg 
-rw-r--r-- 1 pax None 0 2010-08-12 20:55 103xxx.jpg 

images/dir2: 
total 0 
-rw-r--r-- 1 pax None 0 2010-08-12 20:55 103yyy.jpg 

images/dir3: 
total 0 
drwxr-xr-x+ 1 pax None 0 2010-08-12 20:55 dir 4 

images/dir3/dir 4: 
total 0 
-rw-r--r-- 1 pax None 0 2010-08-12 20:55 103zzz.jpg 

Copying from [./dir1/102xxx.jpg] 
      to [../images_renamed/./dir1/102xxx.jpg] and renaming. 

Copying from [./dir1/103xxx.jpg] 
      to [../images_renamed/./dir1/103xxx.jpg] and renaming. 

Copying from [./dir2/103yyy.jpg] 
      to [../images_renamed/./dir2/103yyy.jpg] and renaming. 

Copying from [./dir3/dir 4/103zzz.jpg] 
      to [../images_renamed/./dir3/dir 4/103zzz.jpg] and renaming. 

images_renamed: 
total 0 
drwxr-xr-x+ 1 pax None 0 2010-08-12 21:19 dir1 
drwxr-xr-x+ 1 pax None 0 2010-08-12 21:19 dir2 
drwxr-xr-x+ 1 pax None 0 2010-08-12 21:19 dir3 

images_renamed/dir1: 
total 0 
-rw-r--r-- 1 pax None 0 2010-08-12 21:19 102xxx.jpg 
-rw-r--r-- 1 pax None 0 2010-08-12 21:19 201003xxx.jpg 

images_renamed/dir2: 
total 0 
-rw-r--r-- 1 pax None 0 2010-08-12 21:19 201003yyy.jpg 

images_renamed/dir3: 
total 0 
drwxr-xr-x+ 1 pax None 0 2010-08-12 21:19 dir 4 

images_renamed/dir3/dir 4: 
total 0 
-rw-r--r-- 1 pax None 0 2010-08-12 21:19 201003zzz.jpg 

Pour aplatir la hiérarchie des fichiers, vous pouvez utiliser quelque chose comme:

#!/usr/bin/bash 

rm -rf images_renamed 
ls -lR images 
echo 

cd images 
mkdir -p ../images_renamed 
find . -name '*.jpg' | while read -r; do 
    newfile="$(basename "$REPLY")" 
    echo 'Copying from' [$REPLY] 
    echo '   to' [../images_renamed/$newfile] and renaming. 
    echo 
    cp "$REPLY" "../images_renamed/$newfile" 
    cd ../images_renamed 
    rename 103 201003 "$newfile" 
    cd - >/dev/null 
done 

qui sort:

cd .. 
ls -lR images_renamed 
images: 
total 0 
drwxr-xr-x+ 1 allan None 0 2010-08-12 20:55 dir1 
drwxr-xr-x+ 1 allan None 0 2010-08-12 20:55 dir2 
drwxr-xr-x+ 1 allan None 0 2010-08-12 20:56 dir3 

images/dir1: 
total 0 
-rw-r--r-- 1 allan None 0 2010-08-12 20:55 102xxx.jpg 
-rw-r--r-- 1 allan None 0 2010-08-12 20:55 103xxx.jpg 

images/dir2: 
total 0 
-rw-r--r-- 1 allan None 0 2010-08-12 20:55 103yyy.jpg 

images/dir3: 
total 0 
drwxr-xr-x+ 1 allan None 0 2010-08-12 20:55 dir 4 

images/dir3/dir 4: 
total 0 
-rw-r--r-- 1 allan None 0 2010-08-12 20:55 103zzz.jpg 

Copying from [./dir1/102xxx.jpg] 
      to [../images_renamed/102xxx.jpg] and renaming. 

Copying from [./dir1/103xxx.jpg] 
      to [../images_renamed/103xxx.jpg] and renaming. 

Copying from [./dir2/103yyy.jpg] 
      to [../images_renamed/103yyy.jpg] and renaming. 

Copying from [./dir3/dir 4/103zzz.jpg] 
      to [../images_renamed/103zzz.jpg] and renaming. 

images_renamed: 
total 0 
-rw-r--r-- 1 allan None 0 2010-08-12 22:41 102xxx.jpg 
-rw-r--r-- 1 allan None 0 2010-08-12 22:41 201003xxx.jpg 
-rw-r--r-- 1 allan None 0 2010-08-12 22:41 201003yyy.jpg 
-rw-r--r-- 1 allan None 0 2010-08-12 22:41 201003zzz.jpg 

mais vous devez garder à l'esprit le nom du fichier des affrontements (le même nom de fichier sous différents répertoires) va se remplacer mutuellement.

+0

Est-ce que cela fonctionne récursivement? – scy

+0

Non, vous avez besoin d'une découverte autour de lui. Mise à jour pour montrer une façon de le faire. – paxdiablo

+0

Merci pour votre réponse. La seule chose que je voudrais changer est la destination. Au lieu de conserver la structure de répertoire dans laquelle les fichiers ont été copiés - je veux que toutes les images soient copiées dans le dossier 'images_renamed'. J'ai essayé de changer le script que vous avez fourni mais pas de succès. Je ne peux pas résoudre la relation entre $ REPLY et dirname, basename etc. Je peux dire que $ REPLY est le chemin ful et le nom de fichier que la commande find correspond - mais je peux extraire seulement le nom de fichier de cette information pour l'étape de renommer (c'est-à-dire en utilisant uniquement le nom de fichier, pas le répertoire) – calumbrodie

-1

ont pas testé, mais quelque chose comme ça pourrait fonctionner en bash:

for i in `ls 103*.jpg`; do cp $i newdir/201003${i:3}; done 
+0

Cela ne fonctionne pas avec les sous-répertoires. – scy

+0

utilisation inutile de ls – ghostdog74

0

En ZSH vous pouvez le faire (fonctionne probablement Bash aussi, pas sûr à ce sujet):

for f in **/103*.jpg; mv $f some_other_directory/201003${${f:t}#103} 

Peut-être que je peux aussi vous intéresser dans un outil que j'ai écrit: http://github.com/jkramer/virn Il vous permet de renommer en masse des fichiers en utilisant Vim, y compris toutes les fonctionnalités de Vims comme regex etc.(En fait, vous pouvez aussi utiliser n'importe quel $ EDITOR).

0

Quelque chose comme cela pourrait aider:

cd images 
find . -name '*.jpg' | while read -r img; do 
    mkdir -p "../images_renamed/$(dirname "$img")" 
    cp -v "$img" "../images_renamed/$(echo "$img" | sed -e 's/^103/201003/')" 
done 

Note: Non testé. Ne devrait pas supprimer les choses bien.

+0

Voulez-vous vraiment créer un répertoire pour chaque fichier? –

+0

Ce n'est pas ce que je fais. Je prends le nom de fichier d'origine (y compris le répertoire) et crée ce répertoire et les répertoires possibles au-dessus. Vous pourriez vouloir lire cette ligne encore. – scy

0

Ce qui suit devrait fonctionner:

ls -d images* 
images/   images_renamed/ 


for i in `find images -type f` 
do 
    cp $i images_renamed/$(basename $i | sed s/^103/201003/) 
done 
+0

Ne fonctionne pas si les noms de fichiers contiennent des espaces. Utilisez 'trouver | tandis que lisez et citez les variables qui contiennent des noms de fichiers. –

+0

convenu, mais n'a pas ressenti le besoin de le faire en fonction de la convention de nom de fichier de l'OP. – dogbane

0
find /path -type f -name "10*jpg" | sed 's/.*/mv &/' | sed 's/mv \(.*\/\)\(.[^/]*\)/& \120\2/' | sh 
+0

Jésus. C'est malade. Mais cela pourrait effectivement fonctionner. – scy