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 :

liste de fichier d'un repertoire


Sujet :

Shell et commandes GNU

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 206
    Par défaut liste de fichier d'un repertoire
    Bonjour à tous,

    Je souhaiterais faire un bout de script qui me liste tous les fichiers d'un répertoire, MAIS SANS le chemin.

    Je m'explique : find repertoire -name 'fichier*', va me donner une liste comme ci dessous :
    repertoire/fichier1
    repertoire/fichier2

    Or je voudrais juste
    fichier1
    fichier2

    Etant donné que je sais que je liste les fichiers de repertoire...

    Pour le moment mon script est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for fichier in `find repertoire -name 'fichier*'`;
    do
    	echo $fichier>>listeFichier
    done
    Merci d'avance

  2. #2
    Modérateur
    Avatar de ggnore
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    2 472
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 2 472
    Par défaut
    Bonjour.

    ça aide ?
    Toutes les vertus des hommes se perdent dans l’intérêt comme les fleuves se perdent dans la mer.
    N'oubliez pas de consulter les FAQ Linux et les cours et tutoriels Linux

  3. #3
    Expert confirmé Avatar de frp31
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juillet 2006
    Messages
    5 196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2006
    Messages : 5 196
    Par défaut
    Citation Envoyé par crazykangourou Voir le message
    Bonjour à tous,

    Je souhaiterais faire un bout de script qui me liste tous les fichiers d'un répertoire, MAIS SANS le chemin.

    Je m'explique : find repertoire -name 'fichier*', va me donner une liste comme ci dessous :
    repertoire/fichier1
    repertoire/fichier2

    Or je voudrais juste
    fichier1
    fichier2

    Etant donné que je sais que je liste les fichiers de repertoire...

    Pour le moment mon script est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for fichier in `find repertoire -name 'fichier*'`;
    do
    	echo $fichier>>listeFichier
    done
    Merci d'avance
    find est un traitement par lot, il est donc inutil (voir même interdit en théorie (d'un point de vu algo)) de le metre en boucle !

    il faut faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find ./chemin/ -type f -print | awk -F '/' '{print $NF}'
    et surtout pas de boucle autour d'un find !
    enfin à moins de vouloir multiplier le temps d'exécution par le nombre de fichier trouvés.

  4. #4
    LLB
    LLB est déconnecté
    Membre émérite
    Inscrit en
    Mars 2002
    Messages
    968
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 968
    Par défaut
    Citation Envoyé par frp31 Voir le message
    find est un traitement par lot, il est donc inutil (voir même interdit en théorie (d'un point de vu algo)) de le metre en boucle !
    Pas d'accord.
    Il y a des cas où on peut vouloir effectuer une action sur chaque élément, et l'option -exec n'a pas toujours la souplesse que l'on souhaite.

    Citation Envoyé par frp31 Voir le message
    enfin à moins de vouloir multiplier le temps d'exécution par le nombre de fichier trouvés.
    D'un point de vue théorique, la complexité en temps reste la même. La complexité en espace est plus importante, mais c'est parce qu'il utilise for plutôt que while. Et faire un find | while ne me choque pas plus que ça.

  5. #5
    Expert confirmé Avatar de frp31
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juillet 2006
    Messages
    5 196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2006
    Messages : 5 196
    Par défaut
    Citation Envoyé par LLB Voir le message
    Pas d'accord.
    Il y a des cas où on peut vouloir effectuer une action sur chaque élément, et l'option -exec n'a pas toujours la souplesse que l'on souhaite.
    c'est vrai mais extrèmement rare au pire on fait appeler au -exec une procedure externe (shell script ou autre) si c'est trop complexe.

    D'un point de vue théorique, la complexité en temps reste la même.
    mais pas dans la pratique....

    en formation un find dans un boucle ou |while c'est direct le zéro pointé.
    le formateur se casse même pas à lire la suite du code.

  6. #6
    LLB
    LLB est déconnecté
    Membre émérite
    Inscrit en
    Mars 2002
    Messages
    968
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 968
    Par défaut
    Citation Envoyé par frp31 Voir le message
    mais pas dans la pratique....
    Si.

    En fait, ça dépend du travail à effectuer. Mais compare les 2 lignes suivantes (on est d'accord, ça ne sert à rien, mais c'est pour comparer les temps) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    time find . | while read file; do echo $file; done > /dev/null
    time find . -exec echo {} \; > /dev/null
    La deuxième est... 10 fois plus longue à exécuter. C'est logique : dans le premier cas, il y a en tout 2 (ou 3 ? je ne sais plus) fork nécessaires. Dans le deuxième cas, find n'a pas d'autre choix que de forker pour chaque fichier. La différence est énorme. Juste par echo est une builtin dans le premier cas et un binaire extérieur dans le deuxième.

    While et read sont des builtin, et selon le contenu du script, il fork ou non. Dans tous les cas, le exec doit faire du fork. La première t'économise au final n fork (et cela reste vrai pour les script plus complexes).

    De plus, avoir un while offre bien plus de souplesse. Par exemple, on peut définir une fonction dans le script et l'appeler en boucle. Avec find, tu dois passer par un fichier extérieur... et forker autant de fois (l'appel d'une fonction locale n'engendre pas de fork).

    Au final, je ne dis pas qu'il faut toujours utiliser telle méthode, ça dépend des cas et de ce que l'on veut faire. D'une manière générale, privilégier la lisibilité du code est une bonne chose. Donc, pour un simple exécutable à appeler -exec est bien ; pour les cas plus complexes, while est bien plus clair. Si le formateur met 0 par incompétence, tu peux lui signaler.

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

    Informations forums :
    Inscription : Mai 2004
    Messages : 792
    Par défaut
    Pourquoi pas simplement:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -type f -printf %f\\n

  8. #8
    Rédacteur
    Avatar de Arnaud F.
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Août 2005
    Messages
    5 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Août 2005
    Messages : 5 183
    Par défaut
    @LLB : j'ai testé la différence entre les deux commandes, mais "bizzarement" quand on fait un grep avec les deux commandes que t'as données, c'est celle avec l'option -exec de la commande find qui est plus rapide.

    Normal?

    P.S : je tiens à dire que j'ai envoyé les sorties dans deux fichiers différents et fait un diff dessus, aucune différence
    C'est par l'adresse que vaut le bûcheron, bien plus que par la force. Homère

    Installation de Code::Blocks sous Debian à partir de Nightly Builds

  9. #9
    LLB
    LLB est déconnecté
    Membre émérite
    Inscrit en
    Mars 2002
    Messages
    968
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 968
    Par défaut
    Tu as juste remplacé echo par grep ?
    Dans ce cas, c'est normal que le résultat change : grep est un binaire externe. Donc, que ce soit pour le -exec ou pour le while, il y a le même nombre de forks (à un ou deux près). Le -exec est plus rapide parce qu'il peut appeler directement le grep, tandis que le while passe par du read. Il y a donc une couche supplémentaire. Mais je suppose que la différence entre les deux n'est pas énorme.

    Ma comparaison visait à montrer que, lorsqu'il y a des builtins, while peut être (parfois beaucoup) plus rapide. Avec echo, la différence était flagrante.

    Maintenant, si tu mets ton grep dans un script shell (externe) et tu fais le moins -exec sur ce script shell, je suppose que le -exec sera plus lent : il y aura en tout n forks de plus.

  10. #10
    Rédacteur
    Avatar de Arnaud F.
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Août 2005
    Messages
    5 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Août 2005
    Messages : 5 183
    Par défaut
    pour cette explication


    Je tacherai de m'en souvenir
    C'est par l'adresse que vaut le bûcheron, bien plus que par la force. Homère

    Installation de Code::Blocks sous Debian à partir de Nightly Builds

  11. #11
    LLB
    LLB est déconnecté
    Membre émérite
    Inscrit en
    Mars 2002
    Messages
    968
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 968
    Par défaut
    Explication un peu plus détaillée. J'avais commencé à la taper avant que tu répondes. Normalement, tu n'as pas besoin "de t'en souvenir", il y a juste à comprendre (d'ailleurs, je n'avais jamais réfléchi à ce cas avant hier).

    Le but de ces exemples n'est donc pas vraiment d'optimiser le script (dans 80% des cas, on s'en fiche), mais c'est important de bien comprendre comment fonctionne un shell.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    time find . | while read file; do echo $file; done
    Il y a un fork pour le pipe et un pour le find. C'est tout (while, read et echo étant des builtins du shell).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    time find . -exec echo {} \;
    Il y a un fork pour le find. Ensuite, pour chaque fichier, il faut faire echo. Echo n'étant pas une builtin de find, find n'a pas d'autre choix que de faire appel au binaire echo. Donc, find est contraint de faire un fork par fichier trouvé.

    D'ailleurs, dans cet exemple là, on voit bien l'intérêt d'avoir un binaire echo. Et la raison d'avoir une builtin echo (dans les shells) est évidente : le gain en performance est très important.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -type f -printf %p\\n
    Il y a un fork pour le find. Printf étant une builtin de find, il n'y a pas besoin d'autre fork.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . | while read file; do grep toto $file; done
    Il y a un fork pour le pipe, un pour le find. Ensuite, pour chaque fichier, il est nécessaire de faire un fork, puisque grep n'est pas une builtin du shell.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -exec grep.sh {} \;
    (grep.sh est un script shell qui appelle grep)
    Il y a un fork pour le find. Ensuite, pour chaque fichier, il est nécessaire de faire un fork et d'appeler le shell. Puis, le shell doit faire à nouveau un fork pour appeler le grep. On a donc 2 * n forks.


    Ainsi, find | while a pour avantages :
    - accès aux builtins du shell. Par exemple, si tu voulais lancer alias en boucle sur les résultats, tu n'aurais pas eu le choix.
    - pour ce qui nécessite plusieurs lignes de shell, je pense qu'on gagne en rapidité ; et surtout, en clarté (pas besoin de fichier extérieur).

    Pour les cas basiques (90% des cas), -exec est plus adapté.

  12. #12
    Rédacteur
    Avatar de Arnaud F.
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Août 2005
    Messages
    5 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Août 2005
    Messages : 5 183
    Par défaut
    Qu'une seule chose à dire, merci

    C'est on ne peut plus clair et je me coucherais moins bête ce soir

    C'est par l'adresse que vaut le bûcheron, bien plus que par la force. Homère

    Installation de Code::Blocks sous Debian à partir de Nightly Builds

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 206
    Par défaut oups
    BOnjour,
    Je suis un peu perdu, la discussion est partie dans de très hautes sphères pour moi.
    Pour le moment, il faut que je me familiarise avec les commandes linux.

    Reprenons le problème original :
    J'ai besoin d'exécuter une commande pour chaque nom de fichier que je trouve, d'où l'intérêt de la boucle.

    Je veux bien déplacer le find or de la boucle for, mais comment faire pour ecrire le nom des fichiers que j'ai trouver dans UN fichier nommé liste.txt par exemple?

    Je vais essayer de regarder toutes les options que vous voulez me faire ingurgiter avec man

  14. #14
    LLB
    LLB est déconnecté
    Membre émérite
    Inscrit en
    Mars 2002
    Messages
    968
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 968
    Par défaut
    redirige la sortie standard de la commande dans le fichier spécifié.

    Avec find, tu devrais t'en sortir.

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 206
    Par défaut
    Ok, je viens de tester, ca marche bien,
    merci à vous

    Votre discussion m'a permis de comprendre qu'en fait je n'avais pas besoin de faire de boucle avec find.
    Pire, ce que je ne comprend pas c'est comment ca se fait que je n'ai pas fait de boucle infinie???

  16. #16
    LLB
    LLB est déconnecté
    Membre émérite
    Inscrit en
    Mars 2002
    Messages
    968
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 968
    Par défaut
    Un for n'est pas un while. Il n'y a qu'en C (et ses dérivés) que le for est évalué à chaque boucle.

    En Shell, dans "for i in `cmd`", cmd n'est évalué qu'une seule fois. Et heureusement ! En pratique, le shell évalue cmd, mémorise sa sortie (donc, on évite le for quand la sortie est très longue, du genre le contenu d'un fichier) et boucle sur chacun des résultats.

    Il n'y a donc pas de risque de boucle infinie.

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

Discussions similaires

  1. [XL-2010] liste de fichier d'un repertoire commencant par..
    Par pierjean72 dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 17/10/2013, 12h02
  2. Réponses: 3
    Dernier message: 04/06/2007, 15h32
  3. Réponses: 4
    Dernier message: 08/09/2006, 13h17
  4. [VBS] Liste de fichiers sur un repertoire
    Par sebos63 dans le forum VBScript
    Réponses: 3
    Dernier message: 08/02/2006, 18h13
  5. Réponses: 9
    Dernier message: 27/10/2005, 22h38

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