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 :

find : comment travailler avec "-exec command {}" ?


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 120
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 120
    Par défaut find : comment travailler avec "-exec command {}" ?
    Bonjour,

    J'ai besoin d'effectuer un traitement sur des fichiers dans un dossier.

    Pour les avoir les uns après les autres, j'utilise find ainsi (trouvé dans les exemples du man) :
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    # find . -type f -iname "*.jpg" -exec echo '{}' \;
    ./bidon.JPG
    ./mimosa.jpg
    et on voit que ça fonctionne.

    Mais j'ai besoin de ne récupérer que le nom du fichier, soit enlever l'extension et son point et les 2 premiers caractères du début ("./"), et là, la seule manière que j'ai trouvée consiste à appeler un script secondaire :
    find . -type f -iname "*.jpg" -exec ./suite.sh '{}' \; avec suite.sh =
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
     
    # pour test :
    #echo $1 du script
    # ok, passons à la vraie vie :
     
    fic="$1"
    # supprimer l'extension :
    fic="${fic%.*}"
    # supprimer les 2 premiers caractères :
    fic="${fic:2}"
     
    echo "$fic"
    Je suis content, ça me retourne bien

    Mais question maintenance, ça va être lourd. Une idée pour tout mettre sur la ligne find ?

    Merci et bon dimanche,

  2. #2
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 946
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 946
    Par défaut printf
    Salut,

    Voir les options de printf dans le man find

  3. #3
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 946
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 946
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -type f -iname "*.jpg" -printf '%f\n'
    devrait faire le taf

  4. #4
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 348
    Par défaut
    Citation Envoyé par zipe31 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -type f -iname "*.jpg" -printf '%f\n'
    devrait faire le taf
    Le problème ici, c'est que -exec ne prend pas la valeur que retourne -printf pour traiter la commande passée en paramètre.

    En plus, il faut supprimer aussi l'extension.

  5. #5
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 946
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 946
    Par défaut
    Salut,

    Citation Envoyé par disedorgue Voir le message
    Le problème ici, c'est que -exec ne prend pas la valeur que retourne -printf pour traiter la commande passée en paramètre.
    En plus, il faut supprimer aussi l'extension.
    T'as raison, mea culpa

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -type f -iname "*.jpg" -exec bash -c 'name=${1##*/}; echo "${name%%.*}"' _ {} \;

  6. #6
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 348
    Par défaut
    Citation Envoyé par zipe31 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -type f -iname "*.jpg" -exec bash -c 'name=${1##*/}; echo "${name%%.*}"' _ {} \;


    Une solution comme je les aime.

  7. #7
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 120
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 120
    Par défaut
    Citation Envoyé par zipe31 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -type f -iname "*.jpg" -exec bash -c 'name=${1##*/}; echo "${name%%.*}"' _ {} \;
    Un soupçon d'explication sur cette ligne ésotérique serait la bienvenue, par exemple, le rôle de l'underscore au bout, car si je l'enlève, ça me retourne deux lignes vides.
    Et bash -c, le -c c'est pour dire "ce qui suit entre simple quotes c'est du code" ?

    J'ai légèrement modifié ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -type f -iname "*.jpg" -exec bash -c 'name1=${1##*/}; name2="${name1%%.*}"; echo "$name2"' _ {} \;
    car l'idée de base c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for fic in ./wav do
        fic_sans_ext=${fic##*/}
        fic_épuré=${fic_sans_ext%%.*}
        ffmpeg -i $fic target-dir/$fic_épuré.mp3
    done
    que je teste avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for fic in ./jpg do fic_sans_ext=${fic##*/}; fic_epure=${fic_sans_ext%%.*}; echo $fic_epure.mp3; done
    mais for fic... prend en compte la casse alors que find . -iname... est parfait.

    Plus qu'à tester avec find et en remplaçant echo "$name2" par ffmpeg -i {} target-dir/name2.mp3, genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -type f -iname "*.wav" -exec bash -c 'name1=${1##*/}; name2="${name1%%.*}"; ffmpeg -i $name1 cible/$name2.mp3' _ {} \;
    testé, et ça fonctionne !
    à tous

  8. #8
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 348
    Par défaut
    Bonjour,

    Il manque des éléments sur le besoin comme le comment est passé le résultat à ton traitement: est-ce des arguments ou un flux ?

    Sinon, un exemple simple (pour un flux) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -type f -iname '*.jpg' | sed 's/.*\/\|\.[^.]*$//g'

  9. #9
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 120
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 120
    Par défaut
    Bien bien bien...

    Devant tant de possibilités, je m'en suis remis à l'ami time et un dossier de 16 .wav (700 Mo à la louche) pour pouvoir choisir, et le gagnant est balkany en real et sys, et disedorgue en user :
    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
    # disedorgue
    time { shopt -s nocaseglob; for f in *.wav; do ffmpeg -i "$f" "conv-mp3/${f%.*}.mp3"; done } >/dev/null
    real	1m54.103s
    user	1m52.600s
    sys	0m1.164s
    # balkany
    time { for f in *.[wW][aA][vV]; do ffmpeg -i "$f" "conv-mp33/${f%.*}.mp3"; done } >/dev/null
    real	1m53.839s
    user	1m52.732s
    sys	0m1.000s
    # mézigue
    time find . -maxdepth 1 -type f -iname "*.wav" -exec bash -c 'name1=${1##*/}; name2="${name1%%.*}"; ffmpeg -i $name1 conv-mp333/$name2.mp3' _ {} \; >/dev/null
    real	1m54.008s
    user	1m52.640s
    sys	0m1.232s
    Merci à tous,
    (personne qui s'y connaît en câblage propre de matos audio vintage ?)

  10. #10
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 348
    Par défaut
    Si tu as fait tes tests dans le même terminal et dans l'ordre indiqué, tes résultats ne sont pas viables, puisque tu as activé le nocaseglob sur le test de balkany et donc, potentiellement le ralentir

  11. #11
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 120
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 120
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Si tu as fait tes tests dans le même terminal et dans l'ordre indiqué, tes résultats ne sont pas viables, puisque tu as activé le nocaseglob sur le test de balkany et donc, potentiellement le ralentir
    Ha, je ne l'ai pas supposé ('tain, on en apprendra tous les jours, ).

    Du coup, nouveau terminal, juste la ligne "balkany", et voilà, ça se tient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    real	1m54.718s un peu ralenti
    user	1m52.624s un peu accéléré
    sys	0m1.308s  un peu ralenti
    Bon, on va pas chipoter, faudrait faire des tests sur des milliers de fichiers pour discerner une différence, pas sûr que le jeu en vaille la chandelle.

    Merci encore,

  12. #12
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 288
    Par défaut
    Bonjour

    Du coup, nouveau terminal
    T'es un windowsien, toi, non ?
    Quand tu as tapé un "o" à la place d'un "i", tu ré-installes windows.

    Pour ton info, l'opération inverse de shopt -s nocaseglob est shopt -u nocaseglob. Pour en savoir plus :

  13. #13
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 120
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 120
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Bonjour


    T'es un windowsien, toi, non ?
    Plus depuis mai 2013 (bientôt 7 ans !), mais j'ai pris de mauvaises habitudes, et tenaces. Et pour faire du traitement d'images, c'est quand même plus facile,

  14. #14
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Désolé du retard, je viens de tomber sur ce topic mais il m'a intéressé
    Citation Envoyé par Jipété Voir le message
    Mais j'ai besoin de ne récupérer que le nom du fichier, soit enlever l'extension et son point et les 2 premiers caractères du début ("./"), et là, la seule manière que j'ai trouvée consiste à appeler un script secondaire...
    Mais question maintenance, ça va être lourd. Une idée pour tout mettre sur la ligne find ?
    Le souci inhérent à ton titre (find -exec commande {} \;) c'est que le but de -exec est d'exécuter une commande sur le fichier trouvé par find. Comme par exemple -exec rm -f {} \; pour le supprimer, ou -exec cp {} /tmp \; pour le copier. Bref une action de travail sur le fichier même.

    Or toi, ton but n'est pas de travailler sur le fichier ; mais de changer simplement l'affichage issu de la commande find. Bref tu veux modifier un flux sortant. De là, comme la commande find embarque avec elle une option -printf on peut l'utiliser pour gérer à sa sauce les noms affichés mais si cela n'avait pas été le cas (si le souci était venu d'une autre commande par exemple) alors la solution de disedorgue à base de pipe sur un sed est la plus naturelle du point de vue utilisateur Linux et surtout la plus universelle. On peut ensuite remplacer find par n'importe quelle autre commande renvoyant un flux similaire (ex ls -1 ./* |grep -y jpg) ça fonctionnera tout autant.
    Les autres solutions fonctionnent certainement mais ne sont pas adaptées au but initial (comme celui qui va utiliser un couteau pour dévisser une cruciforme) et surtout pas à base de -exec.

    Citation Envoyé par Jipété Voir le message
    Car l'idée de base c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for fic in ./wav do
        fic_sans_ext=${fic##*/}
        fic_épuré=${fic_sans_ext%%.*}
        ffmpeg -i $fic target-dir/$fic_épuré.mp3
    done
    Là en revanche, on change de registre. Ton but n'est plus d'afficher simplement un résultat de find à l'écran mais bel et bien d'effectuer un travail sur les fichiers trouvés. Donc là oui l'option -exec se justifie et là sera pertinente.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [DW MX2004] Comment travailler avec Excel?
    Par pierrot10 dans le forum Dreamweaver
    Réponses: 3
    Dernier message: 11/05/2006, 17h34
  2. Comment travailler avec Win32
    Par Mathieu.J dans le forum MFC
    Réponses: 4
    Dernier message: 25/01/2006, 09h49
  3. [XSLT] Comment travailler avec la balise <br/>
    Par billou13 dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 11/10/2005, 10h47
  4. Comment travailler avec le port IEEE 1394?
    Par Cornejito dans le forum MFC
    Réponses: 6
    Dernier message: 04/05/2005, 14h22
  5. Comment travailler avec le client ?
    Par mathieu dans le forum Gestion de projet
    Réponses: 3
    Dernier message: 12/10/2004, 20h56

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