IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Script de renommage en sh avec contrainte d'environnement [Débutant(e)]


Sujet :

Shell et commandes GNU

  1. #1
    Membre averti
    Inscrit en
    Novembre 2007
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 21
    Par défaut Script de renommage en sh avec contrainte d'environnement
    Bonjour.

    Je suis débutant en scripting shell, je cherche depuis 2 jours à trouver des solutions pour créer mon script mais là je suis quelque peu bloqué. j'ai du voir la solution sans la trouvé

    Je souhaite faire un script me permettant de renommer les noms de fichiers de mes séries, le plus générique possible.

    Contrainte : environnement linux SYNOLOGY (donc certaines commandes ne sont pas disponible tel que : "TR")

    Le code est peut être fouillis pour un dev qui respect des normes de nomenclatures.

    Voici mon code actuel :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    #!/bin/sh
    OLD_IFS="$IFS";
    IFS=$'\n';
     
    if [ $# -le 2 ]; then
    	cd $1
    	#cdResult=`cd $1`
     
    #	if [ $cdResult -qe false ]; then
    		EpisodeNumber=1;
    		printf "le répertoire courant est désormais : "`pwd`
    		read key
     
    		printf "Saisissez le nom de la série : "
    		read NomDeSerie
    		printf "Le nom de la série est donc : "$NomDeSerie
    		read key
     
    		#printf "Saisissez l'extension (exemple: avi): "
    		#read ext
     
    		for Filename in $(ls *.avi *.mp4 *.mkv);
    		do
    			ext=`expr "$Filename" : ".*\(...\)"`
    			#i=`echo $Filename | awk {'print tolower($_)'}`
    			if [ $EpisodeNumber -le 9 ] ; then 
    				mv $Filename $NomDeSerie"0"$EpisodeNumber.$ext; 
    			else 
    				mv $Filename $NomDeSerie$EpisodeNumber.$ext; 
    			fi
    			EpisodeNumber=$(($EpisodeNumber + 1));
    		done;
    #	else
    #		echo "erreur : Le répertoire est invalide"
    #	fi
    else
    	echo "Il faut saisir le nom du répertoire :  "$0" <nom du répertoire ou chemin complet> "
    fi
    cd ..
    IFS="$OLD_IFS";
    J'aimerais de l'aide pour matcher une valeur d'une string contenu dans une variable:

    Voici mon déroulement logique :

    Exemple nomenclature de fichier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    xxxxxxxxxS05E12.xxx
    xxxxxxxxxxxxxxs05e12.xxx
    xxxxxxxxx512.xxx
    xxxxx05x12.xxx
    
    Ou je me situe ?
    si dossier: ok alors : déplacement dans le dossier
    sinon (output de la commande CD): erreur préciser nom de dossier
    
    logique :
    
    saison = ?
    episode = ?
    
    chaine = chaine en minuscule
    
    1. si 
    s - nombre -> saison
    e - nombre -> episode
    2. si
    nombre - x - nombre => saison - x - episode
    3. detecterai les nombres
     -> si entre 100 et 1000 alors
     1er charactere = saison
     les autres = episode
    
    En gros ça fera ça : 
     
    $nomdeserie = scanf()
     
     for ($origin in $(ls))
     do
     
    	$tmp = Minuscule($origin) # ca je l'ai
    	$saison = 0
    	$episode = 0
    	
    	if [1] then
    	elif [2] then
    	elif [3] then
    	else
    		printf "error : " $origin
    
    	mv $origin $nomdeserie"S"$saison"E"$episode
    		
    	done
    Il est certainement plus facile de le faire en C, mais n'ayant aucune connaissance et souhaitant me familiarisé avec les commandes shell en général je préfère rester sur le shell.

    Je souhaiterais donc savoir quel commande (grep ? sed ? awk ? expr ? cut ?) utiliser pour matcher dans une variable la saison et l'épisode.

    Zt l'autre chose est que je n'arrive pas, en début de code, à récupérer l'output de la commande 'CD', de façon à pouvoir retourner une erreur si la saisie est erroné !

    Merci d'avance pour votre aide.

    PS : si c'est possible d'avoir les explication des commandes que vous me proposer que je comprenne et puisse les réutiliser ultérieurement.

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 56
    Par défaut
    Salut,

    Quand t'auras une solution, je te la piquerai volontiers !
    Un début de réponse : pour avoir le retour de cd, il faut utiliser $? qui donne le retour de la dernière fonction, exemple approximatif :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    cd $(chemin)
    if [ $? -eq 0 ]
       #c'est bon
    Sinon, pour matcher les noms, il faut se tourner vers les expressions régulières mais je ne maitrise pas du tout et peut-être la commande rename si disponible sous ton environnement. Le lien est un peu laconique mais tu peux utiliser rename avec les expressions régulières.
    bon courage

  3. #3
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 730
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 730
    Par défaut
    Bonjour,

    $'\n' n'existe pas en sh, c'est du bash.

    plutôt que de tester le retour de cd, pour tester qu'une variable est un répertoire :on ne fait pas for i in $(commande) outre d'éventuels espaces, les noms de fichiers (ici) peuvent contenir d'autres caractères invisibles, il vaut mieux utiliser le shell for i in liste, qui, lui, protègera les espaces, et autres caractères invisibles.

    matcher dans une variable la saison et l'épisode
    en les comparant à quoi?

  4. #4
    Membre averti
    Inscrit en
    Novembre 2007
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 21
    Par défaut
    Merci pour vos réponses.

    ok pour le test -d "$variable"

    je ne vois pas bien sur quelle variable l'appliquer hormis celle-ci : $1
    et du coup il y a possibilité d'avoir un code erreur de retour ?
    PS: j'ai trouvé ce lien pour le test du coup j'ai modifier mon code de la sorte
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if [ $# -le 2 ]; then
            cdResult=false;
    	test -d $1 && cdResult=true;
     
    	if [ $cdResult == true ]; then
    		cd $1
    		EpisodeNumber=1;
    [...]
    du coup ça fonctionne bien
    Il vaux donc mieux faire for i in liste
    Mais on remplace "liste" par quoi ? c'est une commande qui va lister le contenu du répertoire en retournant les noms des fichiers ?

    il faudrait donc faire quelque choses comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    lsResult=`ls *.avi *.mkv`
    for Filename in lsResult;


    Cependant, j'avais mis ce code suite à des erreurs d'espace justement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    OLD_IFS="$IFS";
    IFS=$'\n';
    en l'enlevant, je retrouve les erreurs dû au espace dans les nom de fichier avec ma boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for Filename in $(ls *.avi *.mkv);


    Pour ce qui est de matcher, ce n'est peut être pas le bon terme que j'ai employé.
    je voudrais analyser ma variable qui contiendra donc le nom du fichier et en se basant sur ces possibilités là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    xxxxxxxxS05E12.xxx
    xxxxxxxxxxxxxxs05e12.xxx
    xxxxxxxxx512.xxx
    xxxxx05x12.xxx
    en déduire la saison et l'épisode.
    j'espère être assez clair.

  5. #5
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 103
    Par défaut
    Citation Envoyé par fifyx Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    xxxxxxxxS05E12.xxx
    xxxxxxxxxxxxxxs05e12.xxx
    xxxxxxxxx512.xxx
    xxxxx05x12.xxx
    en déduire la saison et l'épisode.
    j'espère être assez clair.
    sed, c'est dien pas compliqué:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    case "${filename}" in
        *[Ss][0-9][0-9][Ee][0-9][0-9].???) # cas 1 et 2
            saison=$(echo "${filename}" | sed -e 's:.*[Ss]\([0-9][0-9]\)[Ee][0-9][0-9]\....$:\1:')
            episode=$(echo "${filename}" | sed -e 's:.*[Ss][0-9][0-9][Ee]\([0-9][0-9]\)\....$:\1:')
            ;;
        *[0-9][0-9]?[0-9][0-9].???) # cas 4
            saison=$(echo "${filename}" | sed -e 's:.*\([0-9][0-9]\).[0-9][0-9]\....$:\1:')
            episode=$(echo "${filename}" | sed -e 's:.*[0-9][0-9].\([0-9][0-9]\)\....$:\1:')
            ;;
        *[0-9][0-9][0-9].???) # cas 3
            saison=$(echo "${filename}" | sed -e 's:.*\([0-9]\)[0-9][0-9]\....$:\1:')
            episode=$(echo "${filename}" | sed -e 's:.*[0-9]\([0-9][0-9]\)\....$:\1:')
            ;;
    esac
    En fait, c'est plus facile à écrire qu'à lire!

    Edit: Attention! C'est \1 partout!

  6. #6
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 730
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 730
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if [ $# -le 2 ] # si nb2paramètre_du_script inférieur ou égal à 2; alors
    then
       test -d "$1" && cd "$1" # ne pas oublier les guillemets
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for f in *.avi *.mp4 *.mkv

  7. #7
    Membre averti
    Inscrit en
    Novembre 2007
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 21
    Par défaut
    Citation Envoyé par jack-ft Voir le message
    sed, c'est dien pas compliqué:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    case "${filename}" in
        *[Ss][0-9][0-9][Ee][0-9][0-9].???) # cas 1 et 2
            saison=$(echo "${filename}" | sed -e 's:.*[Ss]\([0-9][0-9]\)[Ee][0-9][0-9]\....$:\1:')
            episode=$(echo "${filename}" | sed -e 's:.*[Ss][0-9][0-9][Ee]\([0-9][0-9]\)\....$:\2:')
            ;;
        *[0-9][0-9]?[0-9][0-9].???) # cas 4
            saison=$(echo "${filename}" | sed -e 's:.*\([0-9][0-9]\).[0-9][0-9]\....$:\1:')
            episode=$(echo "${filename}" | sed -e 's:.*[0-9][0-9].\([0-9][0-9]\)\....$:\2:')
            ;;
        *[0-9][0-9][0-9].???) # cas 3
            saison=$(echo "${filename}" | sed -e 's:.*\([0-9]\)[0-9][0-9]\....$:\1:')
            episode=$(echo "${filename}" | sed -e 's:.*[0-9]\([0-9][0-9]\)\....$:\2:')
            ;;
    esac
    En fait, c'est plus facile à écrire qu'à lire!
    tu pourrais m'expliquer un peu s'il te plait pourquoi utilise tu un "case" ?
    et le sed :p

    -------------------------------------------------------------------------------------
    Citation Envoyé par N_BaH Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if [ $# -le 2 ] # si nb2paramètre_du_script inférieur ou égal à 2; alors
    then
       test -d "$1" && cd "$1" # ne pas oublier les guillemets
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for f in *.avi *.mp4 *.mkv
    j'ai modifié mon message précédent plutôt que de le remettre ici.
    Mais pourquoi tu met
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    test -d "$1" && cd "$1"
    ce que j'ai mis n'est pas correct ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if [ $# -le 2 ]; then
    	cdResult=false;
    	test -d "$1" && cdResult=true;
     
    	if [ $cdResult == true ]; then

  8. #8
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 730
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 730
    Par défaut
    ce que j'ai mis n'est pas correct ?
    pourquoi passer par une variable intermédiaire ?

    case permet d'utiliser des motifs génériques; ce que ne permet pas test.

    le problème avec les espaces vient de l'utilisation de ls; fais comme je t'ai montré, et mets des guillemets autour de tes variables !

  9. #9
    Membre averti
    Inscrit en
    Novembre 2007
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 21
    Par défaut
    je comprend qu'il est mieux d'éviter une variable intermédiaire mais dans ce cas comment procède tu pour la condition du if ?

    tu mettrais ça ?:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if [ $# -le 2 ]; then
    	test -d "$1" && cd "$1";
     
    	if [ $1 == true ]; then
    et pour remplacer le "ls" tu ma montrer ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for f in *.avi *.mp4 *.mkv
    mais aucune commande avant ? à quel moment est fait la liste ?

    il faut mettre des " entre toutes les variables ?

  10. #10
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 730
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 730
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    test -d "$1" && cd "$1" || { echo "\"$1\" n'est pas un répertoire : je sors"; exit 1;}
    il faut mettre des " entre toutes les variables ?
    il faut mettre des guillemets autour de toutes les variables :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var="bla bla"
    echo "$var"
    echo "oulala $var oulala"

  11. #11
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 103
    Par défaut
    Citation Envoyé par fifyx Voir le message
    tu pourrais m'expliquer un peu s'il te plait pourquoi utilise tu un "case" ?
    et le sed :p
    Comme tu présentes 4 formats différents de nom de fichier, je fais un "case" qui s'adapte à chacun de ces 4 cas (en fusionnant les 2 premiers).
    Logique, non?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    saison=$(echo "${filename}" | sed -e 's:.*[Ss]\([0-9][0-9]\)[Ee][0-9][0-9]\....$:\1:')
    Explication du sed:
    .* Chercher n'importe quel caractère (.) en nombre quelconque (*), suivi de
    [Ss] un caractère S ou s, suivi de
    [0-9][0-9] un caractère entre 0 et 9, suivi d'un caractère entre 0 et 9,
    \([0-9][0-9]\) au passage, à cause des parenthèses backslashées, numéroter la sous-chaîne correspondante comme 1 (car c'est la première backslashée rencontrée)
    suivi de
    [Ee][0-9][0-9] un caractère E ou e, suivi d'un caractère entre 0 et 9, suivi d'un caractère entre 0 et 9, suivi de
    \. un caractère point (.), suivi de
    ... trois caractères quelconques (.), suivis de
    $ la fin de la ligne (ou de la chaîne).

    Une fois que sed a trouvé la bête et numéroté ses sous-expressions (une seule, ici),
    's:<le tout>:\1:' remplacer le tout par la première sous-expression (\1)

    C'est clair, chef?

  12. #12
    Membre averti
    Inscrit en
    Novembre 2007
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 21
    Par défaut
    Merci pour vos réponses.

    Citation Envoyé par jack-ft Voir le message
    Comme tu présentes 4 formats différents de nom de fichier, je fais un "case" qui s'adapte à chacun de ces 4 cas (en fusionnant les 2 premiers).
    Logique, non?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    saison=$(echo "${filename}" | sed -e 's:.*[Ss]\([0-9][0-9]\)[Ee][0-9][0-9]\....$:\1:')
    Explication du sed:
    .* Chercher n'importe quel caractère (.) en nombre quelconque (*), suivi de
    [Ss] un caractère S ou s, suivi de
    [0-9][0-9] un caractère entre 0 et 9, suivi d'un caractère entre 0 et 9,
    \([0-9][0-9]\) au passage, à cause des parenthèses backslashées, numéroter la sous-chaîne correspondante comme 1 (car c'est la première backslashée rencontrée)
    suivi de
    [Ee][0-9][0-9] un caractère E ou e, suivi d'un caractère entre 0 et 9, suivi d'un caractère entre 0 et 9, suivi de
    \. un caractère point (.), suivi de
    ... trois caractères quelconques (.), suivis de
    $ la fin de la ligne (ou de la chaîne).

    Une fois que sed a trouvé la bête et numéroté ses sous-expressions (une seule, ici),
    's:<le tout>:\1:' remplacer le tout par la première sous-expression (\1)

    C'est clair, chef?
    Ok pour le case, (je ne le connaissais pas) si je comprend le fonctionnement du case c'est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    case $variable in
    cas 1 # si trouvé alors on exécute les sous-commandes
    sinon on continu
    cas 2 # si trouvé alors on exécute les sous-commandes
    sinon on continu
    etc.
    Correct ?
    cependant pourquoi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    *[Ss][0-9][0-9][Ee][0-9][0-9].???) <= tu ferme la parenthèse que tu n'a pas ouverte ? c'est la nomenclature de case ?
    
    cas1)
      commands
    cas2)
      commands
    et.
    
    dans le cas ou il y a une nomenclature de fichier tel que ça : xxxxxxxxS00E00xxxxxxx.xxx
    est il possible de rajouter la condition "ou" associé aux cas ?
    
    exemple *[Ss][0-9][0-9][Ee][0-9][0-9].???) || *[Ss][0-9][0-9][Ee][0-9][0-9]*.???)

    mais je n'ai pas bien saisie la structure de sed que tu as employé.

    Dans un tutoriel j'ai vu la structure suivante pour la substitution :
    's/modèle/remplacement/drapeau(x)'
    pourquoi commence tu pas "s:"

    si je reprend la nomenclature que j'ai indiqué ci-dessus et l'applique à ton exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    's:.*[Ss]\([0-9][0-9]\)[Ee][0-9][0-9]\....$:\1:'
    
    #le modèle est : n'importe quel caractère (.) numérique (*) (si j'ai compris)
    #le remplacement: "\([0-9][0-9]\)[Ee][0-9][0-9]\...." pourquoi il y a des parenthèse ? c'est pour avoir une écriture comme ça : S(00)E00 ? 
    #si ce n'est pas le cas, quel est le but des ()
    #les drapeaux: :\1 pour indiqué la première itération. si je voulais traiter un fichier pour remplacer plusieurs itération que faudrait il mettre à la place de \1 ?
    et pour remplacer le "ls" tu m'a montré ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for f in *.avi *.mp4 *.mkv
    cependant de quel manière obtenir une liste ?
    de quel manière cela remplace le ls qui me liste le contenu de mon répertoire ?

  13. #13
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 103
    Par défaut
    Citation Envoyé par fifyx Voir le message
    c'est la nomenclature de case ?
    oui
    dans le cas ou il y a une nomenclature de fichier tel que ça : xxxxxxxxS00E00xxxxxxx.xxx
    est il possible de rajouter la condition "ou" associé aux cas ?

    exemple *[Ss][0-9][0-9][Ee][0-9][0-9].???) || *[Ss][0-9][0-9][Ee][0-9][0-9]*.???)
    Ce n'était pas dans les spécifications initiales!
    Pour corriger ton expression, il faut un seul pipe (|) et supprimer la 1ère parenthèse fermante.
    Cependant, un œil averti remarque que ce nouveau cas (un certain nombre de caractères quelconques après le numéro d'épisode) inclut les cas 1 et 2 précédents (où ce certain nombre est précisément 0). On peut donc écrire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    case "${filename}" in
        *[Ss][0-9][0-9][Ee][0-9][0-9]*.???) # cas 1 et 2 (étendus ou pas)
            saison=$(echo "${filename}" | sed -e 's:.*[Ss]\([0-9][0-9]\)[Ee][0-9][0-9].*:\1:')
            episode=$(echo "${filename}" | sed -e 's:.*[Ss][0-9][0-9][Ee]\([0-9][0-9]\).*:\1:')
            ;;
    pourquoi commence tu pas "s:"
    parce que je trouve ça plus joli

    les drapeaux
    Non, non! il n'y a pas de drapeaux. En gras, la partie gauche du substitute, en rouge, la partie droite:

    s/gauche/droite/flags
    s:.*[Ss]\([0-9][0-9]\)[Ee][0-9][0-9]\....$:\1:

    Pourquoi il y a des parenthèse ?
    déjà expliqué: pour numéroter dans la partie gauche une sous-chaîne de la chaîne analysée et pouvoir la référencer dans la partie droite, c'est-à-dire, ici, l'extraire.

  14. #14
    Membre averti
    Inscrit en
    Novembre 2007
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 21
    Par défaut
    Merci pour la réponse.

    non ce n'était pas les spécifications initiales de ma demande, mais comme l'idée m'a traversé l'esprit autant poser la question.

    Par contre j'ai encore du mal à saisir l'intérêt des (), tu dis que ça permet de numéroter la sous-chaîne de la chaîne analysée.
    C'est a dire que c'est un délimiteur pour extraire uniquement ce dont on a besoin ?

    Je viens seulement de voir ta modification "\2" en "\1" suite au fait qu'il me retournait rien !

    d’ailleurs pourquoi il ne me retournait rien ? si j'avais eu cette chaîne il m'aurait retourné une valeur ?
    's:.*[Ss]\([0-9]\)\([0-9]\)[Ee][0-9][0-9].*:\2:'

    si c'est bien ça, alors j'ai enfin compris :/

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Suite à ça:" *[Ss][0-9][0-9][Ee][0-9][0-9]*.???) "
    pourquoi avant le ":\1" tu as mis ".*" et pas ".*\...." #puisque le risque est qu'il y un épisode écris ainsi "xxxx102xxx.avi"
    "  's:.*[Ss]\([0-9][0-9]\)[Ee][0-9][0-9].*:\1:'  "
    Du coup j'ai un autre cas possible dis moi si je me trompe s'il te plait:

    Saison 01, Episode 10 [N°010] - Beauté Fatale.avi

    ce serait bon ça : ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #j'ai ajouté un 
    LESS_FILENAME=`echo $FILENAME| awk {'print tolower($_)'}` 
    # ne me propose pas un 
    " | tr '[:upper:]' '[:lower:]' " ou " sed 's/.*/\U&/' " # ce n'est pas pris en compte par mon environnement
    #avant mon case
    *[saison]*[0-9][0-9]*[episode]*[0-9][0-9]*.???)
    				SAISON=$(echo "${LESS_FILENAME}" | sed -e 's:.*[saison].\([0-9][0-9]\).*[episode].[0-9][0-9].*\....$:\1:')
    				EPISODE=$(echo "${LESS_FILENAME}" | sed -e 's:.*[saison].[0-9][0-9].*[episode].\([0-9][0-9]\).*\....$:\1:')
    				;;

  15. #15
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 103
    Par défaut
    Citation Envoyé par fifyx Voir le message
    C'est a dire que c'est un délimiteur pour extraire uniquement ce dont on à besoin ?
    oui

    Je viens seulement de voir ta modification "\2" en "\1" suite au fait qu'il me retournais rien !
    Oops! Mea culpa! J'aurais dû le signaler plus clairement!

    d'ailleur pourquoi il me retournait rien ? si j'avais eu cette chaîne il m'aurait retourné une valeur ?
    's:.*[Ss]\([0-9]\)\([0-9]\)[Ee][0-9][0-9].*:\2:'

    si c'est bien ça, alors j'ai enfin compris :/
    OUI!

    Ceci dit, il est très simple et TRÈS UTILE de remplacer un "si j'avais eu cette chaîne" par un petit essai (test unitaire), genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ echo xxxxxxxxS05E12.xxx | sed -e 's:.*[Ss]\([0-9]\)\([0-9]\)[Ee][0-9][0-9].*:\2:'
    En fait, j'avais mis \2 parce que je pensais initialement utiliser la même regex pour extraire les 2.
    Du coup, il faudrait vraiment \1 et \2 (et des guillemets pour autoriser l'expansion de la variable ${regex}).
    On peut d'ailleurs combiner les 2.
    Essaie ça tout seul:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    filename=xxxxxxxxS05E12.xxx
    case "${filename}" in
        *[Ss][0-9][0-9][Ee][0-9][0-9]*.???) # cas 1 et 2 (étendus ou pas)
            regexp='.*[Ss]\([0-9][0-9]\)[Ee]\([0-9][0-9]\).*'
            saison=$(echo "${filename}" | sed -e "s:${regexp}:\1:")
            episode=$(echo "${filename}" | sed -e "s:${regexp}:\2:")
     
            echo "${filename}" | sed -e "s:${regexp}:Episode \2 de la saison \1:"
            echo "Episode ${episode} de la saison ${saison}"
            ;;
    esac
    Lorsque tu mets des questions à l'intérieur d'une section de CODE, ce n'est pas très facile à lire!
    Avant de poster sur le forum, merci de cliquer sur "Prévisualisation du message" et de peaufiner la présentation!

    Suite à ça:" *[Ss][0-9][0-9][Ee][0-9][0-9]*.???) "
    pourquoi avant le ":\1" tu as mis ".*" et pas ".*\...."
    #puisque le risque est qu'il y un épisode écris ainsi "xxxx102xxx.avi"
    " 's:.*[Ss]\([0-9][0-9]\)[Ee][0-9][0-9].*:\1:' "
    Je ne comprends pas bien la question.
    Effectivement, ".*\...." est plus rigoureux, mais le risque d'erreur est minime.
    Il faudrait amha un fichier avec soit 2 fois l'info xxxxxxxxS06E13xxS05E12.xxx, soit pas d'extension xxxxxxxxxxS05E12_avi, soit une extension de longueur différente xxxxxxxxxxS05E12.avi_divx
    Normalement, tu as déjà filtré les noms de fichiers en amont!

    Du coup j'ai un autre cas possible dis moi si je me trompe s'il te plait:

    Saison 01, Episode 10 [N°010] - Beauté Fatale.avi

    ce serait bon ça : ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #j'ai ajouté un 
    LESS_FILENAME=`echo $FILENAME| awk {'print tolower($_)'}` 
    # ne me propose pas un 
    " | tr '[:upper:]' '[:lower:]' " ou " sed 's/.*/\U&/' " # ce n'est pas pris en compte par mon environnement
    #avant mon case
    *[saison]*[0-9][0-9]*[episode]*[0-9][0-9]*.???)
    				SAISON=$(echo "${LESS_FILENAME}" | sed -e 's:.*[saison].\([0-9][0-9]\).*[episode].[0-9][0-9].*\....$:\1:')
    				EPISODE=$(echo "${LESS_FILENAME}" | sed -e 's:.*[saison].[0-9][0-9].*[episode].\([0-9][0-9]\).*\....$:\1:')
    				;;
    Pour la conversino en minuscules, essaie de voir si ton shell sait faire ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    A=COUCOU
    typeset -l B=$A
    echo $B
    sinon:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    LESS_FILENAME=$(echo $FILENAME| awk '{print tolower($_)'})
    Pour le reste, c'est presque bon!
    En fait, [Ss] veut dire un caractère parmi S ou s.
    De même [saison] veut dire un caractère parmi a i n o s.
    De même *[saison]* veut dire des caractères quelconques, suivis d'un caractère parmi a i n o s, suivi de caractères quelconques, donc, en pratique, n'importe quelle chaîne, contenant au moins un a i n o ou s, ce qui est effectivement le cas de la chaîne "saison" mais de plein d'autres chaînes aussi!

    Pour matcher "Saison 01, Episode 10 [N°010] - Beauté Fatale.avi" et extraire, j'aurais plutôt utilisé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    case "${filename}" in
        saison?[0-9][0-9],?episode?[0-9][0-9]*)
            regexp='saison \([0-9][0-9]\), episode \([0-9][0-9]\).*'
            saison=$(echo "${filename}" | sed -e "s:${regexp}:\1:")
            episode=$(echo "${filename}" | sed -e "s:${regexp}:\2:")
    on peut aussi faire plus simple (et moins rigoureux) qui permet d'extraire les 2 premiers nombres à 2 chiffres d'une chaîne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    case "${filename}" in
        saison*)
            regexp='[^0-9]*\([0-9][0-9]\)[^0-9]*\([0-9][0-9]\).*'
            saison=$(echo "${filename}" | sed -e "s:${regexp}:\1:")
            episode=$(echo "${filename}" | sed -e "s:${regexp}:\2:")
    [^0-9]* veut dire une chaîne composée d'un nombre quelconque (éventuellement nul) de caractères tous différents d'un chiffre.

  16. #16
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 730
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 730
    Par défaut
    awk pour seulement changer la casse, c'est beaucoup:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo "$vAr" | tr '[[:upper:]]' '[[:lower:]]'
    typeset "risque" de ne pas fonctionner : le script de fifyx est en SH.

  17. #17
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 103
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    awk pour seulement changer la casse, c'est beaucoup:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo "$vAr" | tr '[[:upper:]]' '[[:lower:]]'
    C'est sûr, mais il a indiqué dans son 1er post qu'il était dans un environnement particulier (synology)... SANS 'tr'
    (c'est aussi mentionné à la fin du post 14, mais en moins lisible à cause du formatage!)

    typeset "risque" de ne pas fonctionner : le script de fifyx est en SH.
    Oui, mais il arrive souvent que /bin/sh soit un lien vers un shell plus "moderne" (bash ou dash, par exemple).
    C'est pour ça que je lui propose de tester (s'il n'a pas de contrainte de portabilité).

  18. #18
    Membre averti
    Inscrit en
    Novembre 2007
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 21
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    awk pour seulement changer la casse, c'est beaucoup:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo "$vAr" | tr '[[:upper:]]' '[[:lower:]]'
    typeset "risque" de ne pas fonctionner : le script de fifyx est en SH.
    en sh ou dans ma consol ssh le "typeset" n'est pas reconnu.
    et comme indiqué dans mon poste avant, l'environnement synology n'accepte pas le "tr", ni le "sed 's/.*/\U&/'"

    pour l'utilisation de Sed comme Jack-ft me l'a indiqué, je suis en train de comprendre et les tester.

    Désolé pour le formatage

  19. #19
    Membre averti
    Inscrit en
    Novembre 2007
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 21
    Par défaut
    Citation Envoyé par jack-ft Voir le message

    Pour matcher "Saison 01, Episode 10 [N°010] - Beauté Fatale.avi" et extraire, j'aurais plutôt utilisé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    case "${filename}" in
        saison?[0-9][0-9],?episode?[0-9][0-9]*)
            regexp='saison \([0-9][0-9]\), episode \([0-9][0-9]\).*'
            saison=$(echo "${filename}" | sed -e "s:${regexp}:\1:")
            episode=$(echo "${filename}" | sed -e "s:${regexp}:\2:")
    on peut aussi faire plus simple (et moins rigoureux) qui permet d'extraire les 2 premiers nombres à 2 chiffres d'une chaîne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    case "${filename}" in
        saison*)
            regexp='[^0-9]*\([0-9][0-9]\)[^0-9]*\([0-9][0-9]\).*'
            saison=$(echo "${filename}" | sed -e "s:${regexp}:\1:")
            episode=$(echo "${filename}" | sed -e "s:${regexp}:\2:")
    [^0-9]* veut dire une chaîne composée d'un nombre quelconque (éventuellement nul) de caractères tous différents d'un chiffre.

    si je comprend bien, théoriquement le caractère ^ indique une début de ligne et $ la fin.
    Cependant ^ mis entre crochet, il indique "différent de" suivi du caractère ou d'un ensemble de caractères et le * indique des caractères quelconques.

    pour ce qui est du "?" il correspond à un seul caractère ?

  20. #20
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 103
    Par défaut
    Citation Envoyé par fifyx Voir le message
    si je comprend bien, théoriquement le caractère ^ indique une début de ligne et $ la fin.

    Cependant ^ mis entre crochet, il indique "différent de" suivi du caractère ou d'un ensemble de caractères et le * indique des caractères quelconques.

    pour ce qui est du "?" il correspond à un seul caractère ?
    oui oui oui

    Mais attention, il existe 2 types d'expression!
    La fonction "case" utilise les expressions génériques (où '?' représente un caractère quelconque et '*' un nombre quelconque de caractères quelconques).
    Les commandes "egrep" et "sed" utilisent des expressions régulières (où '.' représente un caractère quelconque et '.*' un nombre quelconque de caractères quelconques).

    Je t'invite à regarder les explications très claires et détaillées de l'utilisation de "sed" (qui m'ont servi de nombreuses fois) fournies par zipe31, par exemple, la dernière en date dans ce post.

Discussions similaires

  1. script envoi mail et fax avec CDO
    Par RobinNono dans le forum ASP
    Réponses: 1
    Dernier message: 03/10/2005, 16h36
  2. UPDATE avec contraintes
    Par Ar-t dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 21/03/2005, 16h20
  3. [Debutant]Suppression dans des tables avec contraintes
    Par Roming22 dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 26/10/2004, 18h23
  4. SELECT : extraire 2 val d'1 colonne avec contraintes diff
    Par NiBicUs dans le forum Langage SQL
    Réponses: 3
    Dernier message: 29/03/2004, 15h56
  5. Script test de deux chaine avec if
    Par kacedda dans le forum Linux
    Réponses: 6
    Dernier message: 02/05/2003, 16h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo