Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 14/08/2011, à 08:44

nassertom

boucle sur l'ensemble des fichiers .mp3 problème avec les espaces

Bonjour,

j'utilise un script qui me permet de convertir des fichiers.

mon problème est que seul les fichiers qui n'ont pas d'espace dans le nom sont vue.

voici un extrait :

#!/bin/bash
if [$1 -e ""]
then
  media_dir="."
else
  media_dir=$1
fi

echo Repertoire selectionné : $media_dir
for i in $media_dir/*.mp3;do  
# on vérifie que $i contient au moins un slash, pour récupérer le chemin du fichier
[[ $i == */* ]] && chemin=${i%/*}/ || chemin=
# on récupère le nom du fichier
nom=${i##*/}
# ici les commandes que je souhaite faire via les variables ${chemin}${nom%.*}
done

si dans mon répertoir j'ai :
ma chanson.mp3
mes-chansons.mp3

seul mes-chansons.mp3 sera vu.

J'ai pensé à utiliser find et iname pour ne plus tenir compte de la casse mais je ne sais pas comment exploiter ma variable $media_dir entre 'quote'

for i in `find . -iname '*.mp3'`;

Question bête :
- je ne sais pas voir ou se termine la boucle 'for' dans le code (une fin comme {} en java ou le next en vb) car par exemple j'aimerais bien faire un 'rm *.mp3' une foi l'ensemble des boucles faite.

D'avance merci,


C'est la plus radicale manière d'anéantir tout discours que d'isoler chaque chose de tout le reste; car c'est par la mutuelle combinaison des formes que le discours nous est né.
[ Le Sophiste, 259e ]

Hors ligne

#2 Le 14/08/2011, à 09:26

TraGiKomiK

Re : boucle sur l'ensemble des fichiers .mp3 problème avec les espaces

Bonjour,

pour ce qui est des espaces la protection par des guillemets ne regle pas le probleme? (pas essayé le script):

for i in $media_dir/"*.mp3";do

Pour find:

for i in `find $media_dir -iname '*.mp3'`;

smile

Dernière modification par TraGiKomiK (Le 14/08/2011, à 09:31)


Merci de mettre [RESOLU] dans le titre de votre post une fois le  probleme reglé!

GNU/Linux -> \o/

Hors ligne

#3 Le 14/08/2011, à 10:58

FRUiT

Re : boucle sur l'ensemble des fichiers .mp3 problème avec les espaces

TraGiKomiK a écrit :
for i in $media_dir/"*.mp3";do

Le glob ne risque pas de marcher dans des guillemets...


Et puis combien de fois faudra-t-il répéter qu'on ne fait jamais un for in $(find) ou for in $(ls) ?

Voici une discussion qui devrait être utile :
Script de renommage récursif

Dernière modification par FRUiT (Le 14/08/2011, à 11:09)


Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean

Hors ligne

#4 Le 14/08/2011, à 11:48

Bousky

Re : boucle sur l'ensemble des fichiers .mp3 problème avec les espaces

Dans ce genre de cas, j'utilise généralement un truc comme ça :

ls -1 "$media_dir/*.mp3" | while read i ; do
        …
done

↑ EDIT : Ben en fait c'est pas une si bonne idée que ça…

Et lorsqu'on a des variables dont on ne maitrise pas le contenu (c'est-à-dire dépendantes des paramètres du script, de l'entrée standard…), on les met toujours entre guillemets doubles, c'est le seul moyen de ne pas créer des problèmes supplémentaires avec les espaces.

Sinon pour séparer le dossier et le fichier, il y a « dirname » et « basename ».

Dernière modification par Bousky (Le 15/08/2011, à 19:55)


Linux qui plante complètement ? Plus rien ne répond ? On peut toujours le redémarrer proprement :
Alt + SysRq + REISUB (Retourne En Islande Sur Un Bateau !)

Hors ligne

#5 Le 14/08/2011, à 12:01

Postmortem

Re : boucle sur l'ensemble des fichiers .mp3 problème avec les espaces

Salut,
@Bousky, suis pas du tout certain que ls -1 "$media_dir/*.mp3"  fonctionne (j'ai pas linux sous la main pour tester). En effet, l'étoile n'est pas traduite entre double-quotes... Donc ça va chercher un fichier s'appelant *.mp3 littéralement.

Puis il ne faut pas "parser" ls ! http://mywiki.wooledge.org/BashPitfalls … .2A.mp3.29 et http://mywiki.wooledge.org/ParsingLs

EDIT : puis le | while read.... va faire s'exécuter la boucle dans un sous-processus et donc, il y a des chances que les variables définies dans ce sous-processus ne soient pas accessibles en dehors de la boucle.

@nassertom : ton idée du début était la bonne pour moi, il faut juste que tu utilises plus de double-quotes.
Tu gardes donc le for i in $media_dir/*.mp3;do qui est très bien comme ça, par contre après, par exemple, les commandes devraient ressembler à ça :
EDIT : non, tu devrais plutôt mettre for i in "$media_dir"/*.mp3;do

chemin="${i%/*}/"
nom="${i##*/}"
mv "${chemin}"/"${nom}" "${chemin}"/"${nom}".old
rm "${chemin}"/"${nom}"

Dernière modification par Postmortem (Le 14/08/2011, à 12:22)


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#6 Le 14/08/2011, à 13:00

Bousky

Re : boucle sur l'ensemble des fichiers .mp3 problème avec les espaces

Postmortem a écrit :

Salut,
@Bousky, suis pas du tout certain que ls -1 "$media_dir/*.mp3"  fonctionne (j'ai pas linux sous la main pour tester). En effet, l'étoile n'est pas traduite entre double-quotes... Donc ça va chercher un fichier s'appelant *.mp3 littéralement.

Effectivement, c'est « "$media_dir"/*.mp3 ».

Le premier lien concerne for, pas « while read ». Le « -1 » sert justement à mettre un fichier par ligne, ce qui supprime le problème des espaces. OK, il reste les sauts de lignes dans les noms de fichiers…

EDIT : puis le | while read.... va faire s'exécuter la boucle dans un sous-processus et donc, il y a des chances que les variables définies dans ce sous-processus ne soient pas accessibles en dehors de la boucle.

Tout dépend de ce que tu veux faire avec.

Je viens de tester, effectivement « for i in * » fonctionne. J'ai pas compris pourquoi…


Linux qui plante complètement ? Plus rien ne répond ? On peut toujours le redémarrer proprement :
Alt + SysRq + REISUB (Retourne En Islande Sur Un Bateau !)

Hors ligne

#7 Le 14/08/2011, à 13:07

Postmortem

Re : boucle sur l'ensemble des fichiers .mp3 problème avec les espaces

Bousky a écrit :

Je viens de tester, effectivement « for i in * » fonctionne. J'ai pas compris pourquoi…

Cela fonctionne car les mots générés par * ne sont pas découpés. Donc même s'il y a un espace dans un développement venant de *, bash le voit comme un simple mot.


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#8 Le 14/08/2011, à 23:39

ehmicky

Re : boucle sur l'ensemble des fichiers .mp3 problème avec les espaces

Salut,
Pour le code que tu as posté initialement, si ton but est de :
  - regarder dans le répertoire donné en argument (répertoire courant par défaut), récursivement, tous les fichiers .mp3
  - d'en extraire, via deux variables, le chemin parent et le nom de fichier
  - d'utiliser ces deux variables via des commandes
Tu peux faire simplement :

find "${1:-.}" -name "*.mp3" -printf "%p\n" | while read ; do
    chemin="${REPLY%/*}"
    nom="${REPLY##*/}"
    #code utilisant "${chemin}/${nom%.*}"
done

("${1:-.}" t'évite de checker le premier argument comme tu sembles vouloir le faire dans les premières lignes de ton script)
Voire, si tu ne veux pas utiliser $chemin et $nom séparément, mais toujours travailler sur le chemin entier du fichier, moins son extension :

find "${1:-.}" -name "*.mp3" -printf "%p\n" | while read ; do
    #code utilisant "${REPLY%.*}"
done

et si tu veux réutiliser les variables déclarer dans la boucle while, en dehors de la boucle :

while read ; do
    #code utilisant "${REPLY%.*}"
done < <(find "${1:-.}" -name "*.mp3" -printf "%p\n")

Dernière modification par ehmicky (Le 14/08/2011, à 23:48)


Stego++, bibliothèque libre de stéganographie (avec cryptographie), à venir !
Besoin de votre aide :
Stats sur les compilateurs C++ les plus utilisés
Comment utiliser les archetypes C++ ?

Hors ligne

#9 Le 15/08/2011, à 03:30

nassertom

Re : boucle sur l'ensemble des fichiers .mp3 problème avec les espaces

Bonjour et merci pour vos réponses.

Alors si j'ai bien compris, il ne faut pas que je fasse un find dans mon for. ça ok.
pour ce qui est de mon problème d'espace des simples double-quote. je n'ai pas encore testé mais moi j’étais parti sur l'utilisation de l'IFS

#pour des espaces dans les noms
oldIFS=$IFS
IFS=$'\\t\\n'
....
IFS=$oldIFS

il y a une chose que je n'arrive pas à comprendre car ce qui ne fonctionne pas, ce n'est pas les données en entrées car sinon ma boucle ne retournerait rien.
par sécurité je vais suivre vos conseils qui j'en suis sur m’aideront à prendre de bonnes habitudes. telle que le for i in "$media_dir"/*.mp3;do

je pense que c'est le fruit de la boucle qui pose problème et donc la variable $i donc en toute logique c'est celle-ci que je devrais mettre entre double quote. c'est ça ?

# on vérifie que $i contient au moins un slash, pour récupérer le chemin du fichier
[[ "$i" == */* ]] && chemin="${i%/*}"/ || chemin=
# on récupère le nom du fichier
nom="${i##*/}"

D'avance merci pour votre aide.
et sinon pour ma question bête... sur les boucles à en lire vos exemples c'est le 'done' qui indique la fin de la boucle ? moi je pensais que le done etait la pour la fin du script. lol


C'est la plus radicale manière d'anéantir tout discours que d'isoler chaque chose de tout le reste; car c'est par la mutuelle combinaison des formes que le discours nous est né.
[ Le Sophiste, 259e ]

Hors ligne

#10 Le 15/08/2011, à 05:56

FRUiT

Re : boucle sur l'ensemble des fichiers .mp3 problème avec les espaces

nassertom a écrit :

Alors si j'ai bien compris, il ne faut pas que je fasse un find dans mon for. ça ok. [...] il y a une chose que je n'arrive pas à comprendre car ce qui ne fonctionne pas, ce n'est pas les données en entrées car sinon ma boucle ne retournerait rien.
par sécurité je vais suivre vos conseils qui j'en suis sur m’aideront à prendre de bonnes habitudes. telle que le for i in "$media_dir"/*.mp3;do

je pense que c'est le fruit de la boucle qui pose problème et donc la variable $i donc en toute logique c'est celle-ci que je devrais mettre entre double quote. c'est ça ?

Je m'auto requote (j'avais mis en lien mais bon........)

FRUiT a écrit :

c'est à cause de l'utilisation conjointe de for et find. Find ne protège pas les noms trouvés avec des guillemets avant de les passer à for, qui lui utilise la variable IFS pour découper le résultat. Donc avec un IFS par défaut (espace, tabulation, saut de ligne) ça ne marche pas car for découpe à chaque espace.

A partir de là plusieurs solutions, changer l'IFS en est une, même si cela est plus du rustinage qu'autre chose.

Effectivement, done marque la fin d'une boucle (for, while, until).

LA solution optimisée est celle de Postmortem (for i in "$media_dir"/*.mp3;do) car elle utilise pleinement les propriétés du développement du glob (*). Le glob (ou masque), contrairement à find ou ls ne renvoie pas une représentation textuelle de noms de fichiers, mais une liste de fichier réels (cf. l'étonnement de bousky). Tout le reste n'est que du bidouillage faisant fi des propriétés intrinsèques du globbing shell.


Autre chose à noter, si for ne découvre aucun fichier mp3, il va utiliser la chaîne littérale « $media_dir/*.mp3 » ($media_dir sera bien développé, mais pas le masque qui restera sous la forme littérale « * ») car il considère alors son alimentation comme une chaîne de caractères et non comme une liste de fichiers. Il convient de toujours tester l'existence pendant la boucle pour éviter ce genre de désagréments (à moins d'être sûr à 100% qu'il y ait des fichiers correspondant au masque mais bon...).

for i in "$media_dir"/*.mp3;do
    [ -f "$i" ] || continue
    ....
done

Dernière modification par FRUiT (Le 15/08/2011, à 06:29)


Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean

Hors ligne

#11 Le 15/08/2011, à 09:46

nassertom

Re : boucle sur l'ensemble des fichiers .mp3 problème avec les espaces

bonjour,
Merci FRUiT pour tes explications precises.

Désolé de ne pas avoir pris le temps de lire le lien de ton premier poste avant de poser ma question.

je place ton lien dans mes postits car il est riche d ensegnement pour quelqu un qui debut en bash.

Poste résolu wink

Dernière modification par nassertom (Le 15/08/2011, à 09:50)


C'est la plus radicale manière d'anéantir tout discours que d'isoler chaque chose de tout le reste; car c'est par la mutuelle combinaison des formes que le discours nous est né.
[ Le Sophiste, 259e ]

Hors ligne

#12 Le 15/08/2011, à 13:30

FRUiT

Re : boucle sur l'ensemble des fichiers .mp3 problème avec les espaces

Mais de rian ^^ bon courage !

PS: Mets aussi en post-it les liens de Postmortem, ils te seront d'un grand secours.
Index des pages : http://mywiki.wooledge.org/BashPitfalls

Dernière modification par FRUiT (Le 15/08/2011, à 13:46)


Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean

Hors ligne