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 :

exécuter une commande sur tous les fichiers des sous dossiers


Sujet :

Shell et commandes GNU

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 127
    Points : 111
    Points
    111
    Par défaut exécuter une commande sur tous les fichiers des sous dossiers
    Bonjour,

    je cherche à effectuer un rechercher/remplacer dans tous les fichiers d'un dossier et ses sous-dossier.

    Concrètement, chaque fichier a exactement le même bloc de code, que je veux remplacer par une seule ligne totalement différente : "MonRemplacement"

    La manière la plus simple (je pense) est d'aller sous linux et d'utiliser vim.

    Voici la commande que j'utilise dans vim pour faire ce remplacement dans un seul fichier, avec les explications sur la syntaxe (expression régulière)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    :s/<HEAD>\n\(^.*\n\)*<\/HEAD>/MonRemplacement
    <HEAD>\n : le début du bloc (la première ligne), avec un retour à la ligne (\n)
    "\(" et "\)" sont des parenthèses capturantes
    "^.*\n" : toute ligne qui finit par un retour à la ligne
    + : autant de ligne que possible (et 1 au minimum)
    </HEAD> : la fin du bloc


    Et maintenant il s'agit d'ouvrir chaque fichier *.php du répertoire (récursivement), et de lancer cette commande vim.

    Il est peut etre possible de le faire sans passer par vim, mais je ne suis pas un expert linux..

    A l'aide !


    Merci d'avance
    Michaël, développeur 2.0 et demi,
    http://www.bacchanales-prod.fr

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    432
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 432
    Points : 593
    Points
    593
    Par défaut
    Tu dois pouvoir faire ça avec la commande sed ?
    Un truc du genre :
    ls [dossier] | cat | sed ...

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    792
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 792
    Points : 1 206
    Points
    1 206
    Par défaut
    A ma connaissance sed ne permet pas de travailler récursivement sans artifice. Deux possibilités:

    Si ta liste de fichier n'est pas trop longue:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed -i 's/a remplacer/remplacement/g' $(find . -name \*.php)
    Si tu as beaucoup de fichiers tu risques de dépasser le nombre d'arguments max de sed. Dnas ce cas, un bon vieux find -exec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -name \*.php -exec sed -i 's/a remplacer/remplacement/g' {} \;
    :q :q! :wq :w :w! :wq! :quit :quit! :help help helpquit quit quithelp
    :quitplease :quitnow :leave :shit ^X^C ^C ^D ^Z ^Q QUITDAMMIT
    Jabber: ripat at im.apinc.org

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 127
    Points : 111
    Points
    111
    Par défaut
    merci de répondre

    ls [dossier] : moi je veux tout les fichiers php d'un dossier et de ses sous dossiers.

    En faisant des tests (et je galère car je met des siècles à trouver une fonction toute bète), je tombe sur quelquechose qui peut convenir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -type f -name "*.php"
    Je pense que mon code peut remplacer ce que tu suggère (le "ls dossier" que je ne sais pas trop comment faire)

    cat : ça affiche toutes les lignes de chaque fichiers (enfin, chaque fichier dont le chemin est donné par une ligne de la commande précédente), c'est ça ?


    sed : je ne connais pas l'utilisation de sed, et j'ai du mal a comprendre la page du manuel de ce dernier.. mon but est un rechercher/remplacer par expression régulière sur plusieurs lignes. J'ai construit cette regex, qui marche quand je l'utilise avec perl sur un seul fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    :s/<HEAD>\n\(^.*\n\)*<\/HEAD>/mynewheader
    Mhhh, bon, après multiples essais, j'ai peut etre trouvé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    // pour un seul fichier :
    vim +'s/<HEAD>\(\n.*\)'*<\/HEAD>/<?php require\(LANG."header.php"\);?> ' fichier1.php
     
    // donc en toute logique
    find . -type f -name "*.php" ;
    do
    vim +'s/<HEAD>\(\n.*\)'*<\/HEAD>/<?php require\(LANG."header.php"\);?> ' fichier1.php
    done
    Si c'est résolu, je mettrait la balise qu'il faut
    Michaël, développeur 2.0 et demi,
    http://www.bacchanales-prod.fr

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    792
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 792
    Points : 1 206
    Points
    1 206
    Par défaut
    Sed utilise la même syntaxe que vim pour le remplacement. Juste plus rapide. Utiliser vim à la place de sed c'est tuer des mouches avec un canon.

    Lis mon post plus haut.
    :q :q! :wq :w :w! :wq! :quit :quit! :help help helpquit quit quithelp
    :quitplease :quitnow :leave :shit ^X^C ^C ^D ^Z ^Q QUITDAMMIT
    Jabber: ripat at im.apinc.org

  6. #6
    Membre expert
    Avatar de hiko-seijuro
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    2 011
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 011
    Points : 3 065
    Points
    3 065
    Par défaut
    ta boucle ca serait plutot :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    list=`find . -type f -name "*.php"`
    for i in $list; do
    	sed +'s/<HEAD>\(\n.*\)'*<\/HEAD>/<?php require\(LANG."header.php"\);?> ' $i
    done
    fais un echo avant de tester brutalement quand meme
    Hiko-seijuro

    n'cha - hoyoyo gang

    espace perso : http://hiko-seijuro.developpez.com
    dernier tuto : Introduction à l'éditeur de texte Emacs sous linux
    consulter les faqs : http://www.developpez.com/faq
    PAS DE QUESTIONS TECHNIQUES PAR MP OU MAIL

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 127
    Points : 111
    Points
    111
    Par défaut
    je teste brutalement mais sur des fichiers de test

    merci à tous pour vos réponses, maintenant je sais comment faire, et de plusieurs façons !

    Hélas, je ne comprend pas pourquoi, le remplacement ne marche plus.. (cf mon message précédent "vim +'s/<HEAD>\(\n.*\)'*<\/HEAD>/<?php require\(LANG."header.php"\);?> ' fichier1.php")

    je vais encore chercher, mais je sens que j'approche du but


    Re-édit : C'est à n'y plus rien comprendre : une recherche sur le mot HEAD ne donne rien, et pourtant il y est !

    Après redémarrage du système, un remplacement se fait ... mais seulement sur la première ligne ! voici mon code (je ne le fais que pour un fichier, tant qu'à faire)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed +'s/<HEAD>\(\n.*\)*\<\/HEAD>/mynewheader/g' test2.php
    Après que cette ligne de commande soit exécutée, il s'affiche mynewheader à la place de <HEAD>, et les autres lignes sont toujours là (alors qu'en toute logique, tout le pattern devrait etre remplacé)

    EDIT again : Euh pardon, je regardais au mauvais endroit, le remplacement ne se fait toujours pas ... Le problème vient des multilignes, le \n ne semble pas pris en compte...


    J'ajoute, à propos de "tuer des mouches avec un canon", si sed est un lance-pierre, ça me dérange pas hein :p

    Sur un autre forum, on m'a dit que sed ne pouvait pas marcher car il ne remplaçait pas en multiligne.

    Pour vim, je pense que ça peut marcher car j'ai déjà réussi (et je n'y arrive plus pour une obscure raison...). je me suis basé sur cette page : http://www.plug.org/pipermail/plug/2...er/012607.html


    Edit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    :%s/<HEAD>\n\_.*\/HEAD/mynewheader/g
    Michaël, développeur 2.0 et demi,
    http://www.bacchanales-prod.fr

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 127
    Points : 111
    Points
    111
    Par défaut
    Voilà, résolu (ou presque, mais le reste c'est de la customisation).

    Je donne la solution, j'espère que ça servira à d'autre !

    Script qui remplace un bloc <HEAD></HEAD> par <?php require('header.php') ?>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ more script_header.sh
    list=`find . -type f -name "*.php"`
    for i in $list; do
        vim +':%s/<HEAD>\_.*<\/HEAD>/<?php require\(LANG."header.php"\); ?> ' +':wq' $i
    done
    Explication :
    list=`find . -type f -name "*.php"`
    find va chercher tout les fichiers (-type f) dont le nom (-name) est "*.php" , et mettre le résultat dans la variable list.

    list est maintenant comme un fichier texte (mais temporaire) qui contient, dans chaque ligne, le chemin pour accéder à tout les fichiers php du dossier et de ses sous dossiers.

    for i in $list; do [COMMANDE] done
    pour chaque ligne de $list, effectuer [COMMANDE]

    vim +':%s/<HEAD>\_.*<\/HEAD>/<?php require\(LANG."header.php"\); ?> ' +':wq' $i
    vim est un éditeur de texte asses complexe. quelques notions : tapez ":i" pour écrire du texte. Pour sauvegarder, appuyez sur la touche d'échappement puis ":w", pour quitter ":q". Pour rechercher remplacer dans vim, on fait ":s/jecherche/jeremplace/". ":%s" c'est comme :s, mais l'expression cherchée peut etre étalée sur plusieurs lignes.

    on peut éditer un fichier directement avec la commande vim monfichier.txt

    on peut également lancer une commande (ou plusieurs) directement en ouvrant un fichier en faisant vim +':s/jecherche/jeremplace/' monfichier.txt

    Cette ligne va donc lancer 2 commandes dans vim : la première effectue un remplacement, la seconde sauvegarde et quitte (les 2 d'un coup). A la fin de la ligne, le nom du fichier ($i puisque c'est la variable de la boucle).
    Michaël, développeur 2.0 et demi,
    http://www.bacchanales-prod.fr

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

Discussions similaires

  1. Exécuter une macro sur tous les onglets d'un fichier sauf un
    Par Marsama dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 07/04/2011, 17h38
  2. [XL-2003] Exécuter une macro sur tous les fichiers d'un dossier.
    Par ahmet dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 16/10/2009, 09h49
  3. Exécuter un commande sur tous les fichiers d'un dossier
    Par Gog077 dans le forum Shell et commandes GNU
    Réponses: 2
    Dernier message: 09/09/2009, 11h55
  4. Réponses: 1
    Dernier message: 18/02/2009, 16h04
  5. Réponses: 18
    Dernier message: 22/06/2006, 17h55

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