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 :

Un mystère de comptage pour éliminer "ls"


Sujet :

Shell et commandes GNU

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 268
    Par défaut Un mystère de comptage pour éliminer "ls"
    Re-bonjour,

    Je veux compter sans ls les objets dans un dossier, et ça semble très facile, exemple avec mon dossier /tmp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ count=0; for obj in /tmp; do count=$((count+1)); done; echo $count
    1
    $ count=0; for obj in /tmp/; do count=$((count+1)); done; echo $count
    1
    $ count=0; for obj in /tmp/*; do count=$((count+1)); done; echo $count
    11
    Voilà donc la bonne syntaxe, sur cette dernière ligne.
    OK.

    Maintenant, je fais ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ target=/media/vide
    $ mkdir $target
    $ count=0; for obj in $target/*; do count=$((count+1)); done; echo $count
    1
    C'est quoi ce "1" ? D'autant plus que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ ls /media/vide
    (ligne vide)
    $ ls -l /media/vide
    total 0
    Ah, cette imbécile de boucle se compte elle-même !, ça se voit bien à l'ajout de echo $obj :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ count=0; for obj in $target/*; do echo "$obj"; count=$((count+1)); done; echo $count
    /media/vide/*
    1
    La bonne syntaxe, avec un test de validité de la variable $obj :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ count=0; for obj in $target/*; do [ -f "$obj" ] && count=$((count+1)); done; echo $count
    0
    $ touch /media/vide/bidon1; touch /media/vide/bidon2; touch /media/vide/bidon3
    $ count=0; for obj in $target/*; do [ -f "$obj" ] && count=$((count+1)); done; echo $count
    3
    $ rm $target/*
    (yCR yCR yCR)
    $ count=0; for obj in $target/*; do [ -f "$obj" ] && count=$((count+1)); done; echo $count
    0
    Ça a l'air correct, alors cadeau.

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

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

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ find ~ -printf "." | wc -c
    34168
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ rm -f ~/testalanoix.txt;find ~ -printf "." | wc -c; >~/testalanoix.txt; find ~ -printf "." | wc -c
    34159
    34160

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 875
    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 875
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Petit ajout :
    Peut-être cela mérite un nouveau topic histoire de ne pas saturer celui-là (si on commence à répondre aux deux sujets à la fois...)
    [edit]Ah, un modo (je suppute que c'est N_BaH) a fait le transfert/scindage de topic

    Citation Envoyé par Jipété Voir le message
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ count=0; for obj in $target/*; do [ -f "$obj" ] && count=$((count+1)); done; echo $count
    0
    Ça a l'air correct, alors cadeau.
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    count=0; while read obj; do count=$((count+1)); done < <(find "$target"/* 2>/dev/null); echo "$count"
    0
    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]

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Septembre 2021
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : Congo-Kinshasa

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Septembre 2021
    Messages : 5
    Par défaut
    Pourquoi vous l'avez appeler un truc ?

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 875
    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 875
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Germain Kausa Voir le message
    Pourquoi vous l'avez appeler un truc ?
    Bonjour, merci, c'est quand tu veux. Tu rentres dans un topic tu dis "bonjour". On te demande pas de le dire à chaque post mais pour le premier du topic.
    Tu veux bien citer la partie dont tu parles qu'on puisse comprendre ta question??? C'est facile, tu fais "répondre avec citation" puis tu supprimes ce qui est en trop...
    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]

  6. #6
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 429
    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 429
    Par défaut
    Non, c'est parce que j'avais posté une réponse par mégarde qui ne fonctionne pas et que j'ai supprimé

  7. #7
    Invité
    Invité(e)
    Par défaut
    Ah, cette imbécile de boucle se compte elle-même !, ça se voit bien à l'ajout de echo $obj
    en bash, il y a l'option nullglob de shopt pour éviter ça.

  8. #8
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 429
    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 429
    Par défaut
    Surtout que test -f check si c'est un fichier "régulier", donc ne compte pas les répertoire et autre type de fichiers possible (socket,bloc,...)

  9. #9
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Jipété
    Je veux compter sans ls les objets dans un dossier[...]
    autrement dit, sans distinguer les fichiers des sous-répertoires, et autres éléments d'un répertoire.

  10. #10
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 429
    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 429
    Par défaut
    donc un simple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ echo $(set -- /tmp/foo/* ; test -a "$1" && echo $# || echo 0)
    0
    $ >"/tmp/foo/bar 3"
    $ echo $(set -- /tmp/foo/* ; test -a "$1" && echo $# || echo 0)
    1
    $ >"/tmp/foo/bar3"
    $ echo $(set -- /tmp/foo/* ; test -a "$1" && echo $# || echo 0)
    2

  11. #11
    Invité
    Invité(e)
    Par défaut
    ${#@}

    $#, c'est tout.

  12. #12
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 429
    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 429
    Par défaut
    Corrigé

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 268
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Peut-être cela mérite un nouveau topic histoire de ne pas saturer celui-là (si on commence à répondre aux deux sujets à la fois...)
    Ah, je ne m'attendais pas à ce que ça démarre aussi vite et fort,

    Citation Envoyé par disedorgue Voir le message
    Surtout que test -f check si c'est un fichier "régulier", donc ne compte pas les répertoire et autre type de fichiers possible (socket,bloc,...)
    Vu ! Avec -a à la place de -f c'est mieux, et ça répond simplement et facilement à mon besoin : savoir si un dossier est vide ou pas.
    (je suis en train de me dire, en relisant, que vous allez me prendre pour le roi des neuneus parce qu'il doit exister plein de manières de trouver cette info, mais j'étais sur les rails de l'autre discussion et bon, pas eu d'autre idée que de compter ce qu'il y a dans le dossier en question.)

    Je verrai le reste de vos réponses plus tard, là j'ai la dalle,

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 268
    Par défaut
    Bonsoir,
    Citation Envoyé par Jipété Voir le message
    Je verrai le reste de vos réponses plus tard, là j'ai la dalle,
    Bon, je n'ai pas eu le temps : problème de raccords de la tuyauterie d'arrosage au jardin, ce truc est un cauchemar terriblement chronophage.

    Citation Envoyé par disedorgue Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ echo $(set -- /tmp/foo/* ; test -a "$1" && echo $# || echo 0)
    Plus le fait que ce genre de ligne, pour moi, est à la limite de la compréhension et si je suis très fort en copier/coller, je suis très mauvais quand il s'agit de modifier une ligne que je ne sais pas lire...

    Alors quand le copier/coller ne se comporte pas comme les quatre premières lignes du code posté sur le forum, je suis perdu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ echo $(set -- /tmp/foo/* ; test -a "$1" && echo $# || echo 0)
    0
    $ >"/tmp/foo/bar 3"
    bash: /tmp/foo/bar 3: Aucun fichier ou dossier de ce type
    $ echo $(set -- /tmp/foo/* ; test -a "$1" && echo $# || echo 0)
    0
    Citation Envoyé par N_BaH Voir le message
    en bash, il y a l'option nullglob de shopt pour éviter ça.
    Oui, il y a toujours un truc ésotérique sorti de derrière les fagots, connu des seuls pratiquants quotidiens de bash, et les autres comme moi vont l'oublier à peine utilisé...
    Ah, si ça se trouve, dans ton dos bash va utiliser un test -a ou similaire,

    Rien compris aux lignes de Flodelarab (je te préfère en Gimp, ), sans explications c'est hard, on dirait le lycée quand il fallait se taper une version latine avec le gros Gaffiot à côté,

    Mais j'aime bien la ligne de Sve@r, qui ressemble beaucoup à la mienne, et qui fonctionne aussi bien, on dirait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ target=/media/vide
    $ count=0; while read obj; do count=$((count+1)); done < <(find "$target"/* 2>/dev/null); echo "$count"
    0
    $ touch $target/test
    $ count=0; while read obj; do count=$((count+1)); done < <(find "$target"/* 2>/dev/null); echo "$count"
    1
    Allez, merci pour tout, bonne soirée et bon dimanche,
    mais faudra choisir entre la boucle avec for (la mienne) et celle avec while (Sve@r)

  15. #15
    Invité
    Invité(e)
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bash: /tmp/foo/bar 3: Aucun fichier ou dossier de ce type
    tu as un répertoire foo/ sous /tmp/ ?

  16. #16
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 429
    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 429
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Bonsoir,

    Bon, je n'ai pas eu le temps : problème de raccords de la tuyauterie d'arrosage au jardin, ce truc est un cauchemar terriblement chronophage.


    Plus le fait que ce genre de ligne, pour moi, est à la limite de la compréhension et si je suis très fort en copier/coller, je suis très mauvais quand il s'agit de modifier une ligne que je ne sais pas lire...

    Alors quand le copier/coller ne se comporte pas comme les quatre premières lignes du code posté sur le forum, je suis perdu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ echo $(set -- /tmp/foo/* ; test -a "$1" && echo $# || echo 0)
    0
    $ >"/tmp/foo/bar 3"
    bash: /tmp/foo/bar 3: Aucun fichier ou dossier de ce type
    $ echo $(set -- /tmp/foo/* ; test -a "$1" && echo $# || echo 0)
    0

    Oui, il y a toujours un truc ésotérique sorti de derrière les fagots, connu des seuls pratiquants quotidiens de bash, et les autres comme moi vont l'oublier à peine utilisé...
    Ah, si ça se trouve, dans ton dos bash va utiliser un test -a ou similaire,
    Bon, là, faut pas déconner, il n'y a rien d'ésotérique ici, pour l'exemple, je crée un fichier "bar 3" dans le répertoire /tmp/foo , il est donc évident qu'il faut créer le répertoire foo dans /tmp si tu veux tester tel quel.
    Et ici, le principe, c'est que au lieu de faire une boucle for qui va passer en revue les éléments d'une liste un par un, je vérifie juste si le premier élément de la liste existe bien en tant que fichier et si oui, j'affiche le nombre d'élément de la liste.

    La méthode de sve@r est la plus lourde mais la plus pérenne selon la quantité de fichier à compter, par contre faudra m'expliquer le pourquoi de la syntaxe du find ("$target"/*) ?
    Pour moi, là, on est sur de l'ésotérique et en plus il fait une descente dans tous les sous-répertoires.

    Et quid pour toutes les solutions, on ne compte pas les noms de type ".xxxx"

    EDIT: en fait la méthode de Flodelarab est plus compact, aussi sure que celle de Sve@r mais plus rapide

  17. #17
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 875
    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 875
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    par contre faudra m'expliquer le pourquoi de la syntaxe du find ("$target"/*) ?
    Pour moi, là, on est sur de l'ésotérique et en plus il fait une descente dans tous les sous-répertoires.
    Oui désolé, j'étais parti de la syntaxe for obj in $target/* et en voyant le code de Flodelarab qui faisait un find je me suis dit qu'il y avait là une idée mais je n'ai pas pensé que la commande descendrait toute l'arborescence.
    Enfin pas bien grave, on rajoute juste un -maxdepth
    Et pourquoi l'étoile ésotérique? Pour spécifier explicitement qu'on veut un truc présent dans le target sinon on retombe dans le travers exposé par Jipété au début, à savoir que find "$target" compte le target lui-même.

    Citation Envoyé par disedorgue Voir le message
    en fait la méthode de Flodelarab est plus compacte
    Euh oui mais pas tout à fait car appliquée à un target vide de cette façon find "$target" -printf "." elle répond "." (donc "1" si on l'envoie à wc).
    Et si on l'applique de cette façon find "$target"/* -printf "." elle renvoie une erreur (la même que la mienne ce qui a nécessité chez-moi le 2>/dev/null)
    Mais mis à part ce détail c'est vrai qu'elle est brillante (en fait je ne l'avais pas pigée au départ)

    Citation Envoyé par disedorgue Voir le message
    mais plus rapide
    Je pourrais faire le N_BaH et dire "ouais mais c'est pas du bash" mais ce serait hypocrite de ma part alors que je défends à chaque fois les avantages qu'il y a à déléguer. Ok, la méthode de Flodelarab est effectivement très brillante
    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]

  18. #18
    Invité
    Invité(e)
    Par défaut
    bah, tant qu'il est question d'éliminer ls , ça me va.
    c'est peut-être un peu surdimensionné pour des fichiers immédiatement disponibles sous le répertoire désigné...
    pour ça, je retiendrais la solution portable strictement POSIX de disdorgue, dont on peut faire une fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ dirElemCnt() ( dir="$1"; set -- "$dir"/*; test -a "$1" && echo $# || echo 0 )
    $ dirElemCnt /tmp
    13
    $

  19. #19
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 429
    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 429
    Par défaut
    Avec une petite correction dans le cas où l'on ne fournit pas d'argument à la fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dirElemCnt() ( [ "$1" ] && set -- "$1"/*; test -a "$1" && echo $# || echo 0 )
    Après, à chacun de voir si la variable "dir" fait plus propre

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 268
    Par défaut
    Bonjour,

    Alors j'ai fait help set et je suis tombé sur ça :
    Citation Envoyé par help_set
    -- Affecte tous les arguments restants aux paramètres de position.
    S'il n'y a plus d'argument, les paramètres de position sont indéfinis.
    qui ne m'avance absolument pas, ne voyant pas du tout de quoi on parle : quels arguments restants ? Quels paramètres de position ?

    Mais comme tout sert à tout, ça m'a fait lire l'aide bash de set, et à qui faut-il écrire pour faire corriger les fautes d'orthographe ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. cherche commande unix pour éliminer les données communes
    Par astrolane dans le forum Applications et environnements graphiques
    Réponses: 3
    Dernier message: 07/12/2009, 17h23
  2. [MySQL] Requête pour éliminer les enregistrements NULL
    Par gtraxx dans le forum PHP & Base de données
    Réponses: 6
    Dernier message: 12/03/2009, 09h09
  3. audacity pour éliminer le bruit
    Par zhpipo16 dans le forum Audio
    Réponses: 5
    Dernier message: 16/04/2008, 20h56
  4. Pb pour éliminer les caractères alpha
    Par chouffe dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 08/12/2005, 11h59

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