Forum Programmation.shell taille liste de fichiers

Posté par  .
Étiquettes : aucune
0
21
déc.
2010
Bon, je me prends la tête avec une connerie... j'arrive pas à trouver une solution...

j'ai une liste de fichier stocké dans un fichier, genre :
/home/toto/file 1
home/toto/file 2

(il y a bien des espaces dans le nom des fichiers, oh monde ingrat !!! :D)

Je veux juste calculer la taille totale des fichiers. j'y arrive pas...

merci!
  • # read

    Posté par  (site web personnel) . Évalué à 4.

    $ while read F ; do du -sb "$F" ; done < /tmp/list | awk '{s+=$1}END{print s}'

    Après, s'il y a des guillemets dans tes noms de fichiers ça devient plus amusant.

    pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

    • [^] # Re: read

      Posté par  (site web personnel) . Évalué à 4.

      On peut gérer les guillemets comme ceci par exemple (je laisse les experts shell montrer leur version) :

      $ perl -ne'chomp;$s+=(stat)[7];END{print"$s\n"}' < /tmp/list

      pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

      • [^] # Re: read

        Posté par  . Évalué à 2.

        merci pour vos réponses.

        en continuant à creuser de mon côté, j'ai fait un truc du genre :

        list=""
        while read line ; do
        [ -e "$line" ] && list= ("$line" "${list[@]}")
        done < $tmp
        echo -e "Total: $(du -hc "${list[@]}"|tail -1)"
        • [^] # Re: read

          Posté par  . Évalué à 2.

          Ton code posera problème si la taille de list dépasse la taille d'une ligne de commande.

          Si tu tiens à optimiser, il est possible de passe par la commande xargs.
          • [^] # Re: read

            Posté par  . Évalué à 1.

            OK, merci pour l'info. Du coup, je vais passer par xargs en effet car la liste peut être plutôt longue...

            merci à tous !
        • [^] # Re: read

          Posté par  . Évalué à 2.

          on peut aussi utiliser wc à la place de du dans ce cas d'usage.
        • [^] # Re: read

          Posté par  . Évalué à 1.

          quand je vois ce genre de ligne de commande, je me dis que c'est trop compliqué pour moi.
          a la base pourquoi pas un ptit truc en C, et là, je me suis dit, encore plus simple (donc moins de risque de bug) un ptit script en php !!!
          $h=fopen("/tmp/list.txt");
          while (($ligne = fgets($h, 4096)) !== false)
          {
          $total+=filesize($ligne);
          }
          echo $total;


          et voilà, on l'utilise avec php -q fichier.php
          j'ai pas testé si les fichiers existent et tout ca... mais c'est assez rapide a ajouter...
          tout simplement...
          • [^] # Re: read

            Posté par  (site web personnel) . Évalué à 2.

            C'est la méthode utilisée par ma ligne de Perl. Sauf qu'elle marchera pour les noms de fichiers de plus 4096 caractères aussi.

            pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

            • [^] # Re: read

              Posté par  . Évalué à 1.

              oui j'avais oublié de préciser qu'il y avait une limite à 4096 sur le nom de chacuns des fichiers. d'un autre coté c'est une limite qui risque d'être atteinte moins souvent que les quelques solution en ligne de commande où on est limité par la dite ligne de commande (tous les nom des fichiers mis bout a bout)
              et d'un autre coté, cette limite, est bien lisible dans le code (qui lui aussi est bien lisible, sans caracteres particuliers)... et qui plus est est modifiable tres facilement.
              par contre pas de prise de tête a savoir s'il y a un espace, un guillemet, un crochet ou autre...

              ensuite la ligne perl, a part le fait que ca tient en une seule ligne, bah ok mais du coups c'est moins evident a lire.
              apres, je prefere faire KISS.

              mais si on veut en plus faire un concours du code le plus petit, c'est une autre question ;)
              • [^] # Re: read

                Posté par  . Évalué à 3.

                L'uniligne n'est qu'une forme du programme tu peut l'écrire ainsi :
                open(FILE,"<toto.txt");
                while () {
                chomp $_;
                $s+=(stat $_)[7];
                }
                print "$s\n";


                C'est compréhenssible du moment que l'on commait le principe de la variable $_.

                Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

          • [^] # Re: read

            Posté par  . Évalué à 2.

            Le C tu dois compiler et gérer ta mémoire tout seul.

            En langage de script perl est juste fait pour ça autant en profiter.
            L'uniligne :
            perl -ne 'chomp;$s+=(stat)[7];END{print"$s\n"}' < /tmp/list
            c'est
            - j'enlève le dernier caractère si c'est un '\n'
            - j'ajoute à la variable s le 7ème élément de la liste renvoyée par stat
            - à la fin du programme afficher la variable s

            Ce qui est génial (mais qu'il faut savoir c'est que la ligne courante (lue dans l'entrée standard est utilisée de manière implicite, on aurait pu écrire :
            perl -ne 'chomp $_;$s+=(stat $_)[7];END{print"$s\n"}' < /tmp/list

            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

            • [^] # Re: read

              Posté par  (site web personnel) . Évalué à 2.

              > - j'ajoute à la variable s le 7ème élément de la liste renvoyée par stat

              C'est le 8ème élément.

              Pour les gens qui veulent décortiquer en détails :

              man perlvar
              man perlrun
              perdoc -f stat
              http://perlgolf.sourceforge.net/

              pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

          • [^] # Re: read

            Posté par  . Évalué à 1.

            ouai mais à la base, je code un script pour une applications écrite en bash. plowshare pour ne pas la citer. Je rajoute des fonctions plus haut niveau à cet outil (gestion de la maj des listes, affichage des statuts, redémarrage après plantages, etc.).
            Ca devrait atterrir bientôt sur le wiki du projet.

            Du coup, je reste sur ma solution bash. Mais le perl et le C était en effet des solutions intéressantes.

            merci pour votre aide !

            lien du projet : http://code.google.com/p/plowshare/
      • [^] # Re: read

        Posté par  . Évalué à 3.

        au fait ça peut être raccourcis non ?
        $ perl -lnE '$s+=(stat)[7]; END{say "$s"}' < /tmp/list

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

        • [^] # Re: read

          Posté par  (site web personnel) . Évalué à 2.

          Intéressant, je ne connaissais pas. La documentation de -E n'est pas très parlante par contre :

          -E commandline
          behaves just like -e, except that it implicitly enables all optional features (in the main compilation unit). See feature.

          Et je ne trouve aucune section à propos de ces « features ».

          pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

  • # xargs

    Posté par  . Évalué à 6.

    Rien ne vaut un bon vieux xargs :
    $ xargs -d"\n" du -c < fichier
    • [^] # Re: xargs

      Posté par  (site web personnel) . Évalué à 2.

      S'il y a suffisamment de fichiers, cette solution ne produira pas un total puisqu'il y aura eu plusieurs invocations de du(1).

      pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.