Précédent   Forum des professionnels en informatique > Systèmes > Linux > Applications > Shell
Shell Vos questions sur l'utilisation des commandes shell
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 29/10/2007, 16h12   #1
Membre du Club
 
Inscription : juin 2006
Messages : 206
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 206
Points : 47
Points : 47
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 :
1
2
3
4
5
 
for fichier in `find repertoire -name 'fichier*'`;
do
	echo $fichier>>listeFichier
done
Merci d'avance
crazykangourou est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/10/2007, 16h39   #2
Modérateur
 
Avatar de ggnore
 
Inscription : juillet 2004
Messages : 2 246
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : juillet 2004
Messages : 2 246
Points : 1 904
Points : 1 904
Bonjour.

ça aide ?
__________________
Toutes les vertus des hommes se perdent dans l’intérêt comme les fleuves se perdent dans la mer.
ggnore est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/10/2007, 07h42   #3
Expert Confirmé Sénior
 
Avatar de frp31
 
Homme francois
Ingénieur systèmes et réseaux
Inscription : juillet 2006
Messages : 3 546
Détails du profil
Informations personnelles :
Nom : Homme francois
Âge : 35
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 : 3 546
Points : 7 779
Points : 7 779
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 :
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 :
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.
frp31 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/10/2007, 16h31   #4
LLB
Membre Expert
 
Inscription : mars 2002
Messages : 946
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 946
Points : 1 085
Points : 1 085
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.
LLB est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/10/2007, 07h18   #5
Expert Confirmé Sénior
 
Avatar de frp31
 
Homme francois
Ingénieur systèmes et réseaux
Inscription : juillet 2006
Messages : 3 546
Détails du profil
Informations personnelles :
Nom : Homme francois
Âge : 35
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 : 3 546
Points : 7 779
Points : 7 779
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.

Citation:
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.
frp31 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/10/2007, 10h47   #6
LLB
Membre Expert
 
Inscription : mars 2002
Messages : 946
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 946
Points : 1 085
Points : 1 085
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 :
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.
LLB est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/11/2007, 14h15   #7
Membre émérite
 
Inscription : mai 2004
Messages : 709
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : mai 2004
Messages : 709
Points : 852
Points : 852
Pourquoi pas simplement:

Code :
find . -type f -printf %f\\n
__________________
: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
ripat est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/11/2007, 22h58   #8
Rédacteur
 
Avatar de Arnaud F.
 
Homme Arnaud Feltz
Développeur .NET
Inscription : août 2005
Messages : 5 204
Détails du profil
Informations personnelles :
Nom : Homme Arnaud Feltz
Âge : 25
Localisation : France

Informations professionnelles :
Activité : Développeur .NET
Secteur : Transports

Informations forums :
Inscription : août 2005
Messages : 5 204
Points : 6 113
Points : 6 113
@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
Arnaud F. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/11/2007, 23h16   #9
LLB
Membre Expert
 
Inscription : mars 2002
Messages : 946
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 946
Points : 1 085
Points : 1 085
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.
LLB est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/11/2007, 23h26   #10
Rédacteur
 
Avatar de Arnaud F.
 
Homme Arnaud Feltz
Développeur .NET
Inscription : août 2005
Messages : 5 204
Détails du profil
Informations personnelles :
Nom : Homme Arnaud Feltz
Âge : 25
Localisation : France

Informations professionnelles :
Activité : Développeur .NET
Secteur : Transports

Informations forums :
Inscription : août 2005
Messages : 5 204
Points : 6 113
Points : 6 113
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
Arnaud F. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/11/2007, 23h53   #11
LLB
Membre Expert
 
Inscription : mars 2002
Messages : 946
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 946
Points : 1 085
Points : 1 085
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 :
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 :
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 :
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 :
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 :
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é.
LLB est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/11/2007, 00h18   #12
Rédacteur
 
Avatar de Arnaud F.
 
Homme Arnaud Feltz
Développeur .NET
Inscription : août 2005
Messages : 5 204
Détails du profil
Informations personnelles :
Nom : Homme Arnaud Feltz
Âge : 25
Localisation : France

Informations professionnelles :
Activité : Développeur .NET
Secteur : Transports

Informations forums :
Inscription : août 2005
Messages : 5 204
Points : 6 113
Points : 6 113
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
Arnaud F. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/11/2007, 10h47   #13
Membre du Club
 
Inscription : juin 2006
Messages : 206
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 206
Points : 47
Points : 47
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
crazykangourou est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/11/2007, 10h52   #14
LLB
Membre Expert
 
Inscription : mars 2002
Messages : 946
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 946
Points : 1 085
Points : 1 085
redirige la sortie standard de la commande dans le fichier spécifié.

Avec find, tu devrais t'en sortir.
LLB est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/11/2007, 11h01   #15
Membre du Club
 
Inscription : juin 2006
Messages : 206
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 206
Points : 47
Points : 47
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???
crazykangourou est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/11/2007, 11h12   #16
LLB
Membre Expert
 
Inscription : mars 2002
Messages : 946
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 946
Points : 1 085
Points : 1 085
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.
LLB est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 04h23.


 
 
 
 
Partenaires

Hébergement Web