2010-06-03 5 views
0

Je ne sais pas vraiment grand-chose sur les scripts bash OU imagemagick, mais j'essaye de créer un script dans lequel vous pouvez donner une sorte de motif correspondant à une liste d'images puis les traiter dans de nouveaux fichiers ayant un préfixe de nom de fichier donné.redimensionner des images avec imagemagick via un script shell

par exemple donné la liste dir suivante:

allfiles01.jpg allfiles02.jpg allfiles03.jpg

je voudrais appeler le script comme ceci:

./resisemany.sh allfiles*.jpg 30 newnames*.jpg 

le résultat final de ce serait que vous obtenez un tas de nouveaux fichiers avec de nouveaux noms, les chiffres correspondent,

jusqu'à ce que j'ai est:

IMAGELIST=$1 
RESIEZFACTOR=$2 
NUMIMGS=length($IMAGELIST) 

for(i=0; i<NUMIMGS; i++) 
    convert $IMAGELIST[i] -filter bessel -resize . RESIZEFACTOR . % myfile.JPG 

Merci pour toute aide ... Les pièces que j'ai besoin évidemment aide sont 1. Comment donner un critère correspondant script bash qu'il comprend 2 comment utiliser le $ 2 sans le faire correspondre au deuxième élément de la liste d'images 3. comment obtenir la longueur de la liste d'images 4. comment créer une boucle appropriée dans un tel cas 5. comment faire correctement remplacement de texte pour une commande de shell par laquelle vous ajoutez des éléments comme je le fais.

JML

+0

Cela ne fonctionnera pas comme vous le souhaitez. –

+0

existe-t-il une solution équivalente? – jml

Répondre

4

probablement la façon dont un programme standard fonctionnerait serait de prendre un « dans » modèle de nom de fichier et un modèle de nom de fichier « out » et effectuer l'opération sur chaque fichier dans le répertoire courant qui correspond à la « dans "motif, en substituant les parties appropriées dans le" out "modèle. Ceci est assez facile si vous avez un modèle codé en dur, lorsque vous pouvez écrire des commandes ponctuelles comme

for infile in *.jpg; do convert $infile -filter bessel -resize 30% ${infile//allfiles/newnames}; done 

Afin de faire un script qui va le faire avec tout modèle, cependant, vous avez besoin quelque chose de plus compliqué parce que la transformation de votre nom de fichier pourrait être quelque chose de plus compliqué que de simplement remplacer une partie par une autre. Malheureusement Bash n'a pas vraiment vous donner un moyen d'identifier quelle partie du nom de fichier correspondant d'une partie spécifique du motif, de sorte que vous auriez à utiliser un moteur d'expression régulière plus capable, comme sed par exemple:

#!/bin/bash 

inpattern=$1 
factor=$2 
outpattern=$3 
for infile in *; do 
    outfile=$(echo $infile | sed -n "s/$inpattern/$outpattern/p") 
    test -z $outfile && continue 
    convert $infile -filter bessel -resize $factor% $outfile 
done 

cela pourrait être invoquée comme

./resizemany.sh 'allfiles\(.*\).jpg' 30 'newnames\1.jpg' 

(notez les guillemets simples!) et il redimensionner allfiles1.jpg-newnames1.jpg, etc. Mais vous auriez vent en ayant essentiellement pour apprendre la syntaxe d'expression régulière de sed de préciser votre modèles d'entrée et de sortie. (Ce n'est pas si mal que ça, vraiment)

+0

Je dois dire que je préfère apprendre awk et sed sur perl, puisque je travaille en python pour la plupart des choses que perl ferait. merci beaucoup pour cette solution. – jml

1

Votre script doit être appelé en utilisant une syntaxe telle que:

./resizemany.sh -r 30 -n newnames -o allfiles allfiles*.jpg 

et utiliser getopts pour traiter les options.Ce que vous ne savez peut-être pas, c'est que l'interpréteur de commandes étend le fichier glob avant que le script ne l'obtienne, de sorte que, comme vous aviez vos arguments, votre script ne serait jamais capable de distinguer les noms des autres paramètres.

Les fichiers de sortie seront nommés en utilisant le script rename souvent trouvé sur les systèmes sur lesquels Perl est installé. Un fichier nommé "allfiles03.jpg" sera édité sous "newname03.jpg".

#!/bin/bash 

options=":r:n:o:" 
while getopts $options option 
do 
    case $option in 
     n) 
      newnamepattern=$OPTARG 
      ;; 
     o) 
      oldnamepattern=$OPTARG 
      ;; 
     r) 
      resizefacor=$OPTARG 
      ;; 

     \?) 
      echo "Invalid option" 
      exit 1 
    esac 
done 
# a check to see if any options are missing should be performed (not implemented) 
shift $((OPTIND - 1)) 
# now all that's left will be treated as filenames 
for file 
do 
    convert (input options) "$file" -resize $resizefactor (output options) "${file}.out" 
    rename "s/$old/$new/;s/\.out$//" "${file}.out" 
done 

Ceci est non testé (évidemment, puisque la plupart des arguments à convert sont portés disparus).

La validation des paramètres, tels que les vérifications de portée, les options manquantes requises et autres, sont conservés en tant qu'exercices pour un développement ultérieur. Également absentes sont les vérifications pour la réussite d'une étape avant de passer à la suivante. Des problèmes tels que l'emplacement des fichiers et des collisions de noms et d'autres ne sont pas abordés.

5

Vous pouvez éliminer le problème de regex si vous faites un dossier de tous les fichiers à traiter, puis exécutez quelque chose comme:

for img in `ls *.jpg` 
do 
    convert $img -filter bessel -resize 30% processed-$img 
done 

Ensuite, si vous avez besoin de les renommer, vous pouvez tout faire plus tard quelque chose comme:

ls | nl -nrz -w2 | while read a b; do mv "$b" newfilename.$a.jpg; done; 

aussi, si vous faites un traitement par lots de la même opération, vous pouvez voir si vous utilisez mogrify pourrait aider (méthode de ImageMagik pour convertir plusieurs fichiers). Comme dans l'exemple ci-dessus, il est toujours bon de faire une copie du dossier, puis d'exécuter tout traitement afin de ne pas détruire vos fichiers d'origine.

Questions connexes