[SHELL] Renommer les noms de fichiers avec espaces

Renommer les noms de fichiers avec espaces [SHELL] - Shell/Batch - Programmation

Marsh Posté le 03-03-2010 à 14:18:06    

Contexte : KSH  
 
Question récurrente, rébarbative et sans doute revisitée souvent mais.... (y a toujours un 'mais' bien marrant  :na: )
 
Pas de souci pour modifier l'affichage des noms de mes fichiers, un truc tout con genre ce qui suit suffit :

Code :
  1. ls | sed 's/  */_/g'


 
Seulement Quid quand il s'agit de renommer ces fichiers ? car là, quand on fait une boucle avec un ls ou un find, le paramètre itératif de la boucle contient systématiquement une découpe en fonction des espaces, et du coup c'est la mouïse !
 
Explication par l'exemple :
 

Code :
  1. for fic in $( ls )
  2. do
  3.    mv "$fic" `echo $fic | sed 's/  */_/g'`
  4. done


 
Ben là ça fonctionne plus du tout, car le ls lui, il vous découpe tout avec les espaces....  :kaola:  :fou:  :o  :non:  
 
J'avoue je cale en peu aujourd'hui, les neurones semblent fatigués.
 
Merci d'avance pour l'éventuel coup de main


Message édité par Kerrozen le 03-03-2010 à 14:18:29

---------------
En programmation, quand t'as un problème et qu'il n'y a que deux solutions valides, seule la troisième fonctionne !
Reply

Marsh Posté le 03-03-2010 à 14:18:06   

Reply

Marsh Posté le 03-03-2010 à 14:31:05    

Bon, finalement les neurones se sont réveillés grâce à Google qui est mon ami.
 
La commande magique est la suivante :
 

Code :
  1. for i in *
  2. do
  3.        mv "$i" `echo "$i" | sed 's/  */_/g'`
  4. done


 :love:  :love:  :love:  
 
Ce qui est vraiment bébête, je le reconnais   :jap:  
 
En revanche, comprendre pourquoi quand on utilise un ls ça fonctionne pas et pourquoi donc ça fonctionne avec *  ...... alors là....... Si un gourou local pouvait me faire un petit topo, mes neurones et moi même serions tout à fait comblés !
 
Merci quand même ! (ben oui, le fait d'écrire ici donne l'impression qu'on doit tout faire pour trouver une réponse avant les autres ^^ c'est motivant !)


---------------
En programmation, quand t'as un problème et qu'il n'y a que deux solutions valides, seule la troisième fonctionne !
Reply

Marsh Posté le 03-03-2010 à 15:22:45    

Beaucoup de monde utilise for sans se méfier que cela coupe les variable là où se trouve une fin de ligne ou un espace. Je ne sais pas pourquoi for in * marche. En tous cas, j'utilise read qui marche sans problème.
 
Voici un script de test :

echo "=== 1. for i in dollar( ls ) ==="
for i in $( ls )
do
   echo $i
done
 
echo "=== 2. ls | while read i ==="
ls | while read i
do
   echo $i
done
 
echo "=== 3. for i in * ==="
for i in *
do
   echo $i
done

Dans mon répertoire, j'ai

fichier un.txt
fichier_deux.txt
test1.sh

Le résultat est :

=== 1. for i in dollar( ls ) ===
fichier
un.txt
fichier_deux.txt
test1.sh
=== 2. ls | while read i ===
fichier un.txt
fichier_deux.txt
test1.sh
=== 3. for i in * ===
fichier un.txt
fichier_deux.txt
test1.sh


Reply

Marsh Posté le 23-03-2010 à 10:54:16    

En ce qui concerne le read, je suis moins étonné : il va de lui même stocker toute la ligne qu'il lit avec ses espaces et autres tabulations (donc ce que tu lui envoie via le pipe ) directement dans une variable. Là donc pas de problème. J'aurai d'ailleurs effectivement pu réagir tout de suite en l'utilisant plutôt que d'insister avec mon FOR : bien vu !
 
Mais quand même, j'avais bien compris la méthode de découpe du for : espaces, sauts de lignes, tabulations etc etc... et c'est bien pour ça que je suis assez interloqué par le comprtement avec "*" ?
 
Personne ne saurait nous donner le détail avancé de ce qui se passe ?


---------------
En programmation, quand t'as un problème et qu'il n'y a que deux solutions valides, seule la troisième fonctionne !
Reply

Marsh Posté le 27-03-2010 à 17:37:00    

Kerrozen a écrit :

Mais quand même, j'avais bien compris la méthode de découpe du for : espaces, sauts de lignes, tabulations etc etc... et c'est bien pour ça que je suis assez interloqué par le comprtement avec "*" ?
 
Personne ne saurait nous donner le détail avancé de ce qui se passe ?


 
C'est parce que l'étoile est transformée par le programme chargé de lire le clavier et transmettre ensuite l'ordre lu au shell.
Et ce logiciel encadre alors tout fichier avec espace par deux quottes simples '     '
 
Suffit d'activer le débuggueur shell "set -x" et de taper ensuite "echo *". Le débuggueur montrera la vraie commande reçue et on voit les noms avec espace encadré de ces quottes.
 
Partant de là, si le répertoire contient un fichier "a a", on comprend pourquoi un for i in * ne découpe pas le nom "a a" car le shell aura reçu 'a a' (un seul token bien protégé) alors que for i in `ls` lui fait recevoir a a (2 tokens apparemment non liés)


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 27-03-2010 à 21:03:30    

olivthill a écrit :

Je ne sais pas pourquoi for in * marche.


 
Le shell échappe les caractères spéciaux. :)

Reply

Marsh Posté le 30-03-2010 à 10:22:06    

Sve@r a écrit :


 
C'est parce que l'étoile est transformée par le programme chargé de lire le clavier et transmettre ensuite l'ordre lu au shell.
Et ce logiciel encadre alors tout fichier avec espace par deux quottes simples '     '
 
Suffit d'activer le débuggueur shell "set -x" et de taper ensuite "echo *". Le débuggueur montrera la vraie commande reçue et on voit les noms avec espace encadré de ces quottes.
 
Partant de là, si le répertoire contient un fichier "a a", on comprend pourquoi un for i in * ne découpe pas le nom "a a" car le shell aura reçu 'a a' (un seul token bien protégé) alors que for i in `ls` lui fait recevoir a a (2 tokens apparemment non liés)


 
 :bounce:  :jap:  :jap:  :jap:  :jap:  :jap:  :bounce:  
 
J'savais bien que j'aurai la réponse en venant causer ici ! Merci beaucoup à Sve@r !
On en apprend tous les jours.


---------------
En programmation, quand t'as un problème et qu'il n'y a que deux solutions valides, seule la troisième fonctionne !
Reply

Sujets relatifs:

Leave a Replay

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