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 :

utilisation de {} dans find -exec et commandes imbriquées


Sujet :

Shell et commandes GNU

  1. #1
    Membre expert
    Avatar de pitipoisson
    Homme Profil pro
    Chercheur
    Inscrit en
    Septembre 2006
    Messages
    1 942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Chercheur
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 942
    Points : 3 378
    Points
    3 378
    Par défaut utilisation de {} dans find -exec et commandes imbriquées
    Bonjour à tous,

    Une petite question, plus pour satisfaire ma curiosité que pour résoudre un véritable problème d'application...

    En cherchant une solution plus direct au problème soulevé dans cette discussion : script pour naviguer dans une arborescence, je suis tombé sur un autre problème, que je n'ai su résoudre ni en parcourant les différents tutoriels, FAQ, etc. ni avec man find (peut-être n'ai-je simplement pas su où regarder).
    Je met ma question dans une discussion à part, car elle sort un peu du cadre de l'original.

    Voilà ce que j'ai essayé de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     mkdir -p ./toto/titi/tata
     touch ./toto{,/titi{,/tata}}/essai.exe
     
    # Tentative de suppression des extensions.
    # Ne fonctionne pas : -exec n'aimerait-il pas les références {} imbriquées dans d'autres commandes ?
     find -name "*.exe" -type f -exec mv '{}' `basename '{}' .exe` \;
    Ce qui m'a valu les insultes suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    mv: `./toto/essai.exe' and `./toto/essai.exe' are the same file
    mv: `./toto/titi/essai.exe' and `./toto/titi/essai.exe' are the same file
    mv: `./toto/titi/tata/essai.exe' and `./toto/titi/tata/essai.exe' are the same file
    Il semble donc que la référence '{}' (j'ai également essayé de ne plus la protéger : {} => même résultat) qui se trouve dans une commande imbriquée (entre `...`, est-ce la bonne dénomination ?), ne soit absolument pas prise en compte.

    Savez-vous s'il existe une façon de contourner ce problème ?

    [Edit: à bien y réfléchir, j'imagine que le shell cherche à évaluer ce qui est entre `...` avant la commande find, y a-t-il un moyen de lui signifier que ça doit être fait à chaque itération de -exec ... ? ]
    Forum LaTeX : pour des réponses rapides et appropriées, pensez à poster un
    ECM = Exemple (reproduit le problème) Complet (document compilable) Minimal (ne postez pas votre thèse !)

    Une solution vous convient ? N'oubliez pas le tag


    )><))))°>

  2. #2
    Invité
    Invité(e)
    Par défaut
    Salut,

    si tu fais un find -name "*.exe" -> tu auras dans {} le nom du fichier .exe

    -> mv <fichier>.exe en basename <même_fichier> auquel tu ajoutes à nouveau l'extension .exe -> on reviendra au même point de départ! d'où le message d'erreur.

  3. #3
    Membre expert
    Avatar de pitipoisson
    Homme Profil pro
    Chercheur
    Inscrit en
    Septembre 2006
    Messages
    1 942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Chercheur
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 942
    Points : 3 378
    Points
    3 378
    Par défaut
    Citation Envoyé par Mygale1978 Voir le message
    -> mv <fichier>.exe en basename <même_fichier> auquel tu ajoutes à nouveau l'extension .exe -> on reviendra au même point de départ! d'où le message d'erreur.
    Non, le problème ne vient pas de là, la commande entre `...` est justement sensée supprimer l'extension.

    Pour t'en convaincre, en reprenant l'exemple précédent, limité à cette partie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ find -name "*.exe" -type f -exec basename '{}' .exe \;
    essai
    essai
    essai
    .exe n'est là que pour signifier à la commande basename quelle est l'extension à supprimer.
    Si je voulais en ajouter une autre, je ferais quelque chose du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    `basename '{}' .exe`.txt
    (enfin si je pouvais utiliser '{}' )

    Edit: pour aller plus loin dans le raisonnement...
    En fait, je pense que le message d'erreur vient du fait que la commande `...` ne retourne rien. Du coup, le comportement par défaut de mv, c'est de placer le fichier, avec le même nom, dans le répertoire qui est pointé (. à partir de là où est trouvé le fichier .exe).
    Ce ne pourrait pas être simplement ça ?
    Forum LaTeX : pour des réponses rapides et appropriées, pensez à poster un
    ECM = Exemple (reproduit le problème) Complet (document compilable) Minimal (ne postez pas votre thèse !)

    Une solution vous convient ? N'oubliez pas le tag


    )><))))°>

  4. #4
    Membre éprouvé

    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2007
    Messages : 552
    Points : 1 058
    Points
    1 058
    Par défaut
    Bonjour.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    find -name "*.exe" -type f | xargs -I file echo file file
    find -name "*.exe" -type f | xargs -I file echo file echo file
    La première affiche la liste des fichiers en doublant les noms. On peut donc utiliser deux fois le "retour" de la commande find.
    Par contre la deuxième affiche les noms des fichiers en les séparant par le mot echo. Seul la première commande est prise en compte apparament.
    ZiK un lecteur audio et son blog.

  5. #5
    Membre expert
    Avatar de pitipoisson
    Homme Profil pro
    Chercheur
    Inscrit en
    Septembre 2006
    Messages
    1 942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Chercheur
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 942
    Points : 3 378
    Points
    3 378
    Par défaut
    Citation Envoyé par vinc-mai Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    find -name "*.exe" -type f | xargs -I file echo file file
    find -name "*.exe" -type f | xargs -I file echo file echo file
    La première affiche la liste des fichiers en doublant les noms. On peut donc utiliser deux fois le "retour" de la commande find.
    Par contre la deuxième affiche les noms des fichiers en les séparant par le mot echo. Seul la première commande est prise en compte apparament.
    Merci pour cette remarque.
    C'est normal que le second cas ne fonctionne pas : le second echo est un paramètre du premier. Il n'est donc pas évalué.

    En fait, le problème n'est pas tant d'utiliser deux fois la référence que de l'utiliser dans une commande évaluée en premier.
    Et ton exemple me donne une piste intéressante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ find -name "*.exe" -type f | xargs -I file echo file `echo file`
    ./toto/essai.exe ./toto/essai.exe
    ./toto/titi/essai.exe ./toto/titi/essai.exe
    ./toto/titi/tata/essai.exe ./toto/titi/tata/essai.exe
    Forum LaTeX : pour des réponses rapides et appropriées, pensez à poster un
    ECM = Exemple (reproduit le problème) Complet (document compilable) Minimal (ne postez pas votre thèse !)

    Une solution vous convient ? N'oubliez pas le tag


    )><))))°>

  6. #6
    Membre expert
    Avatar de pitipoisson
    Homme Profil pro
    Chercheur
    Inscrit en
    Septembre 2006
    Messages
    1 942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Chercheur
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 942
    Points : 3 378
    Points
    3 378
    Par défaut
    Espoir de courte durée, je n'arrive toujours pas à enlever l'extension entre des ``:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ find -name "*.exe" -type f | xargs -I file echo file `basename file .exe`
    ./toto/essai.exe ./toto/essai.exe
    ./toto/titi/essai.exe ./toto/titi/essai.exe
    ./toto/titi/tata/essai.exe ./toto/titi/tata/essai.exe
    Et surtout, je n'arrive pas à comprendre comment on en arrive à ce résultat ???

    Je ne vais pas trop persévérer aujourd'hui, mais toutes les idées sont les bienvenues.
    Forum LaTeX : pour des réponses rapides et appropriées, pensez à poster un
    ECM = Exemple (reproduit le problème) Complet (document compilable) Minimal (ne postez pas votre thèse !)

    Une solution vous convient ? N'oubliez pas le tag


    )><))))°>

  7. #7
    Membre éclairé Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Points : 823
    Points
    823
    Par défaut
    Bonsoir,

    J'ai une solution simple mais très imparfaite:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find toto -name "*.txt" -exec mv {} {}.txt \;
    Je ne fais qu'ajouter une extension supplémentaire, je ne la remplace pas.

    Edit Oups, petite erreur: dans le find, il s'agit de "*.exe", pas de "*.txt"
    Un problème bien posé est déjà résolu (H. Bergson).

  8. #8
    Membre éclairé Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Points : 823
    Points
    823
    Par défaut
    Sinon, une solution qui marche, mais plus compliquée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find toto -name "*.exe" | awk '{ newFile=gensub("exe$", "txt", 1); system("mv " $0 " " newFile) }'
    Un problème bien posé est déjà résolu (H. Bergson).

  9. #9
    Membre expert
    Avatar de pitipoisson
    Homme Profil pro
    Chercheur
    Inscrit en
    Septembre 2006
    Messages
    1 942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Chercheur
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 942
    Points : 3 378
    Points
    3 378
    Par défaut
    Citation Envoyé par jmelyn Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find toto -name "*.exe" | awk '{ newFile=gensub("exe$", "txt", 1); system("mv " $0 " " newFile) }'
    C'est vrai qu'on sort un peu du cadre des "solutions directes"... mais ça marche parfaitement

    En plus, mes notions de AWK ont beau être très rudimentaires, je trouve cette ligne de code tout à fait compréhensible (j'irais quand même pas jusqu'à dire que je l'aurais trouvée tout seul ).

    Comme la question concernait plus spécifiquement l'utilisation de références '{}' de find entre ` `, je laisse la discussion ouverte quelques temps encore.

    Ceci dit, ma curiosité a déjà trouvé de quoi se nourrir. Merci à tous ceux qui ont pris la peine de participer.
    Forum LaTeX : pour des réponses rapides et appropriées, pensez à poster un
    ECM = Exemple (reproduit le problème) Complet (document compilable) Minimal (ne postez pas votre thèse !)

    Une solution vous convient ? N'oubliez pas le tag


    )><))))°>

  10. #10
    Membre éclairé
    Avatar de D[r]eadLock
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 504
    Points : 747
    Points
    747
    Par défaut
    Citation Envoyé par pitipoisson Voir le message
    Espoir de courte durée, je n'arrive toujours pas à enlever l'extension entre des ``:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ find -name "*.exe" -type f | xargs -I file echo file `basename file .exe`
    ./toto/essai.exe ./toto/essai.exe
    ./toto/titi/essai.exe ./toto/titi/essai.exe
    ./toto/titi/tata/essai.exe ./toto/titi/tata/essai.exe
    Et surtout, je n'arrive pas à comprendre comment on en arrive à ce résultat ???
    .
    En fait le contenu de `` est executé avant de faire ton find ! C'est pourquoi dans ton problème original tu as deux fois le même fichier car `basename {} .exe` donne {} Du coup dans ton find original tu as -exec mv {} {} !

    Par contre ceci "marche":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    > find . -name '*.exe' -exec bash -c "echo {} \`basename {} .exe\`" \;
    ./toto/titi/tata/essai.exe essai
    ./toto/titi/essai.exe essai
    ./toto/essai.exe essai
    Par contre je ne sais pas ce que tu voulais faire au début, mais tu perds le répertoire...

  11. #11
    Membre expert
    Avatar de pitipoisson
    Homme Profil pro
    Chercheur
    Inscrit en
    Septembre 2006
    Messages
    1 942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Chercheur
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 942
    Points : 3 378
    Points
    3 378
    Par défaut
    Citation Envoyé par D[r]eadLock Voir le message
    En fait le contenu de `` est executé avant de faire ton find ! C'est pourquoi dans ton problème original tu as deux fois le même fichier car `basename {} .exe` donne {} Du coup dans ton find original tu as -exec mv {} {} !
    Bon-sang, mais c'est bien sûr !
    Je n'avais pas du tout pensée que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ basename {} .exe
    {}


    Citation Envoyé par D[r]eadLock Voir le message
    Par contre ceci "marche":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    > find . -name '*.exe' -exec bash -c "echo {} \`basename {} .exe\`" \;
    ./toto/titi/tata/essai.exe essai
    ./toto/titi/essai.exe essai
    ./toto/essai.exe essai
    Par contre je ne sais pas ce que tu voulais faire au début, mais tu perds le répertoire...
    Alors là, chapeau ! Je suis bluffé !

    Bon, le "problème" du répertoire qui disparaît devrait facilement se contourner avec un petit dirname*.

    J'ai pas trop le temps de jouer à l'adapter, ce matin, je posterai la réponse ultime et définitive (?) plus tard...

    Merci

    * Edit: dirname... ou rien du tout, avec -execdir qui, me semble-t-il, exécute la commande à partir du répertoire où est trouvé un fichier.
    Forum LaTeX : pour des réponses rapides et appropriées, pensez à poster un
    ECM = Exemple (reproduit le problème) Complet (document compilable) Minimal (ne postez pas votre thèse !)

    Une solution vous convient ? N'oubliez pas le tag


    )><))))°>

  12. #12
    Membre expert
    Avatar de pitipoisson
    Homme Profil pro
    Chercheur
    Inscrit en
    Septembre 2006
    Messages
    1 942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Chercheur
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 942
    Points : 3 378
    Points
    3 378
    Par défaut Solution...
    Bon, pour finir, voici une solution qui fonctionne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find toto -name "*.exe" -type f -exec bash -c "mv '{}' \`dirname '{}'\`/\`basename '{}' .exe\`.txt" \;
    Donc, pour conclure, si l'on vaut utiliser une construction de la forme `... '{}' ... ` dans un find avec l'option -exec, il faut :
    1. mettre la commande dans une chaîne de caractères (elle n'est donc pas évaluée avant le find)
    2. lancer une instance de bash qui exécute la commande contenue dans la chaîne de caractères (option -c)


    Il faut noter que l'utilisation de l'option -execdir pour éviter un dirname pose problème: elle essaye d'exécuter ./mv ! (ce qui bien évidement ne fonctionne pas).

    Merci à tous.
    Forum LaTeX : pour des réponses rapides et appropriées, pensez à poster un
    ECM = Exemple (reproduit le problème) Complet (document compilable) Minimal (ne postez pas votre thèse !)

    Une solution vous convient ? N'oubliez pas le tag


    )><))))°>

  13. #13
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Je suis tomber sur ce post en cherchant à maitriser l'action -exec de find.

    Si l'on revient au problème de départ (supprimer les extensions), est ce que la ligne suivante n'aurait pas suffit ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find <chemin> -name "*.exe" -exec rename s/\.exe$// {} \;
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find <chemin> -name "*.exe" -exec rename s/\.exe$/\.txt/ {} \;
    si l'on veut renommer .exe en .txt par exemple.

    Cela dit je ne suis pas sûr que la commande rename soit dispo sur tous les unix, mais on est sur un forum linux non ?
    Dernière modification par Invité ; 07/09/2009 à 14h07.

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

Discussions similaires

  1. pattern paramètrable dans find en ligne de commande
    Par radiobrain dans le forum Linux
    Réponses: 2
    Dernier message: 12/07/2008, 18h25
  2. Utiliser exec plusieurs fois dans find
    Par Tex-Twil dans le forum Shell et commandes GNU
    Réponses: 0
    Dernier message: 12/03/2008, 15h49
  3. utilisation de l'option -exec de find
    Par panach91 dans le forum Shell et commandes GNU
    Réponses: 10
    Dernier message: 17/01/2008, 12h34
  4. verifier la suppression dans le exec du find
    Par decksroy dans le forum Linux
    Réponses: 4
    Dernier message: 04/12/2007, 12h45
  5. Réponses: 5
    Dernier message: 02/03/2006, 10h38

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