for file in `ls /test`

for file in `ls /test` - Codes et scripts - Linux et OS Alternatifs

Marsh Posté le 05-02-2006 à 14:39:06    

Hello,  
 
je fais un petit script pour redimensioner des photos.  
Je recontre juste un petit problème: dans mon script je traite tous les fichiers du rep 1 par 1 via un:
for file in `ls /test; do
...
done
 
Le prob est qu'il considère par exemple le fichier  blabla 1.jpg comme deux fichiers distincts car il y a un espace.
 
Y'a-t-il une astuce pour palier à ca?  
 
D'avance merci

Reply

Marsh Posté le 05-02-2006 à 14:39:06   

Reply

Marsh Posté le 05-02-2006 à 15:37:07    

bon ben pour le moment j'ai fais un rename qui remplace les espaces par un _ mais bon c'est pas top je trouve.

Reply

Marsh Posté le 05-02-2006 à 16:03:31    

for file in `ls test`; do
la_commande "file" argument...
done

EDIT:
oops, j'ai oublié le $ de la variable :

Code :
  1. for file in `ls test`; do
  2. la_commande "$file" argument...
  3. done

Message cité 1 fois
Message édité par _kal_ le 05-02-2006 à 19:53:56
Reply

Marsh Posté le 05-02-2006 à 17:16:15    

_kal_ a écrit :

for file in `ls test`; do
la_commande "file" argument...
done

nop.
 
Deux solutions :

Code :
  1. # je ne sais pas ce que tu fais dans ton code, tu n'as peut être pas besoin de cette ligne
  2. cd /test || exit
  3.  
  4. for file in *
  5. #for file in /test/*
  6. do
  7.    mv "$file" machin
  8.    # etc
  9. done


 
ou
 

Code :
  1. OLD_IFS="$IFS"
  2.  
  3. IFS=
  4.  
  5. for i file in `ls /test`
  6. do
  7.        mv "$file" machin
  8.        # etc
  9.        # il faut faire attention, la valeur de l'IFS n'étant pas celle par défaut, certaines choses
  10.        # ne fonctionneront pas si tu fais des choses compliquées dans ta boucle, tu seras probablement
  11.        # obligé de restaurer/effacer la valeur d'IFS à chaque itération.
  12. done
  13.  
  14. IFS="$OLD_IFS"
  15.  
  16. #suite du script


Reply

Marsh Posté le 05-02-2006 à 19:27:49    

Pillow a écrit :

nop.
 
Deux solutions :

Code :
  1. # je ne sais pas ce que tu fais dans ton code, tu n'as peut être pas besoin de cette ligne
  2. cd /test || exit
  3.  
  4. for file in *
  5. #for file in /test/*
  6. do
  7.    mv "$file" machin
  8.    # etc
  9. done


 
ou
 

Code :
  1. OLD_IFS="$IFS"
  2.  
  3. IFS=
  4.  
  5. for i file in `ls /test`
  6. do
  7.        mv "$file" machin
  8.        # etc
  9.        # il faut faire attention, la valeur de l'IFS n'étant pas celle par défaut, certaines choses
  10.        # ne fonctionneront pas si tu fais des choses compliquées dans ta boucle, tu seras probablement
  11.        # obligé de restaurer/effacer la valeur d'IFS à chaque itération.
  12. done
  13.  
  14. IFS="$OLD_IFS"
  15.  
  16. #suite du script



 
Excuse moi mais c'est pareil. J'ai par contre effectivement oublié le $, mais c'est bien les guillement qui empeche la coupure en différent mots  :jap:

Reply

Marsh Posté le 05-02-2006 à 20:01:50    

_kal_ a écrit :

Excuse moi mais c'est pareil. J'ai par contre effectivement oublié le $, mais c'est bien les guillement qui empeche la coupure en différent mots  :jap:

Non. Ce qui pose problème, c'est que le word splitting se produit lors de la substitution de commande et lors du for. Il n'y a qu'à tester :

Code :
  1. % bash
  2. $ touch "foo bar"
  3. $ touch baz
  4. $ for file in `ls`; do echo "$file"; done
  5. baz
  6. foo
  7. bar
  8. $ for file in *; do echo "$file"; done
  9. baz
  10. foo bar

On peut aussi utiliser read :

Code :
  1. $ ls | while read file; do echo "$file"; done
  2. baz
  3. foo bar


 

Reply

Marsh Posté le 05-02-2006 à 20:17:17    

Merde alors, j'été persuadé que mettre des guillemets corigeait le problème. En fait, c'est l'utilisation aussi du masque * au lieu de `ls` qui fait que ca marche comme on veu. Peux tu m'expliquer pourquoi, je vois pas trop la ... ;)

Reply

Marsh Posté le 06-02-2006 à 15:57:17    

_kal_ a écrit :

Merde alors, j'été persuadé que mettre des guillemets corigeait le problème. En fait, c'est l'utilisation aussi du masque * au lieu de `ls` qui fait que ca marche comme on veu. Peux tu m'expliquer pourquoi, je vois pas trop la ... ;)

Le shell execute le code dans cet ordre : substitution de commande, puis word splitting, puis pathname expansion.
 

Code :
  1. for file in `ls`

1) ls est exécuté.
2) `ls` est remplacé par la sortie de cette exécution (ici, une liste de deux mots, "baz" et "foo bar" ).
3) Le shell procède au word splitting en utilisant l'IFS. Par défaut l'IFS contient l'espace, la tablature et le retour à la ligne (je ne sais plus l'ordre des deux derniers, mais bref). On a donc trois mots : baz, foo, bar.
 
Ça ne marche pas.
 
On veut donc éviter l'étape 3. Pour cela, on peut enlever l'espace de l'IFS : lors de l'étape du word splitting, "foo bar" ne sera plus découpé en deux mots, et notre code fonctionnera alors correctement.
 

Code :
  1. for file in *

1) Le shell procède au word splitting. Il n'y a qu'un caractère, '*', donc comme l'IFS par défaut ne contient pas '*', il ne se passe rien.
2) Le shell remplace '*' par la liste des fichiers du répertoire courant. Ici, une liste de deux mots, "baz" et "foo bar".
 
Ça marche ! [:zytrayaisse]  
 

Reply

Marsh Posté le 06-02-2006 à 16:38:12    

merci !  [:1337]

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed