12
votes

Comment puis-je lire récursivement des répertoires à Perl?

Je veux lire de manière récursive un répertoire pour imprimer la structure de données dans une page HTML avec modèle :: Toolkit. Mais je suis suspendu à la manière de sauvegarder les chemins et les fichiers sous une forme qui peut être lu notre solution facile.

Mon idée a commencé comme ceci xxx

Comment puis-je résoudre ce problème?


0 commentaires

6 Réponses :


9
votes

Vous devez toujours utiliser des avertissements stricts et des avertissements pour vous aider à déboguer votre code. Perl aurait averti que vous vous avertiez par exemple que @files code> n'est pas déclaré. Mais le vrai problème avec votre fonction est que vous déclarez une variable lexicale @paths code> sur chaque appel récursif vers list_dirs code> et ne repoussez pas la valeur de retour après l'étape de la récursivité.

use strict;
use warnings;
use File::Find qw(find);

sub list_dirs {
        my @dirs = @_;
        my @files;
        find({ wanted => sub { push @files, $_ } , no_chdir => 1 }, @dirs);
        return @files;
}


3 commentaires

Avec cette routine, je n'obtiens qu'un seul résultat, et c'est le répertoire que je donne la routine pour commencer.


Pouvez-vous me montrer le code que vous utilisez pour examiner cela? Ça marche juste bien ici. Peut-être le tester avec "Utilisez dumbre; imprimé Dumper List_Dirs '/ Home'".


Pouvez-vous s'il vous plaît expliquer ce qui se passe dans la commande ? Il a l'air cryptique pour un novice Perl.



3
votes

Je pense que vous avez un problème dans la ligne suivante dans votre code xxx

Vous modifiez la variable $ chemin en $ rootpath.

Il stockera correctement le chemin.


0 commentaires

20
votes

Cela devrait faire le tour xxx


2 commentaires

Donc, GLOB ne prend pas en charge la liste récursive des fichiers, non?


C'est correct, cela n'aura que les fichiers du répertoire donné.



5
votes

La réponse de MDOM explique comment votre tentative initiale s'est égarée. Je suggère également que vous envisagez des alternatives plus amicales à Fichier :: Trouver code>. CPAN a plusieurs options. Voici un.

use strict;
use warnings;

print $_, "\n" for dir_listing(@ARGV);

{
    my @paths;
    sub dir_listing {
        my ($root) = @_;
        $root .= '/' unless $root =~ /\/$/;
        for my $f (glob "$root*"){
            push @paths, $f;
            dir_listing($f) if -d $f;
        }
        return @paths;
    }
}
  • So Réponse Fournir au CPAN Alternatives à Fichier :: Rechercher CODE>. P> LI>

  • donc question sur les itérateurs de répertoires. p> li> ul>

    Et voici une réécriture de votre solution récursive. Choses à noter: Utilisez strict code>; Utiliser des avertissements code>; et l'utilisation d'un bloc de décomposition pour créer une variable statique pour le sous-programme. p> xxx pré> p>


0 commentaires

1
votes

J'utilise ce script pour supprimer des fichiers cachés (créés par Mac OS X) de mon USB Pendrive, où je l'utilise habituellement pour écouter de la musique dans la voiture et tout fichier se terminant par ".mp3", même quand il commence par "._", sera répertorié dans la liste audio de la voiture.

#!/bin/perl

use strict;
use warnings;

use File::Find qw(find);

sub list_dirs {
        my @dirs = @_;
        my @files;
        find({ wanted => sub { push @files, $_ } , no_chdir => 1 }, @dirs);
        return @files;
}

if ( ! @ARGV || !$ARGV[0] ) {
  print "** Invalid dir!\n";
  exit ;
}


if ( $ARGV[0] !~ /\/Volumes\/\w/s ) {
  print "** Dir should be at /Volume/... > $ARGV[0]\n";
  exit ;
}

my @paths = list_dirs($ARGV[0]) ;

foreach my $file (@paths) {
  my ($filename) = ( $file =~ /([^\\\/]+)$/s ) ;

  if ($filename =~ /^\._/s ) {
    unlink $file ;
    print "rm> $file\n" ;
  }
}


0 commentaires

1
votes

Vous pouvez utiliser cette méthode comme recherche de fichiers récursif qui distingue des types de fichiers spécifiques,

my @files;
push @files, list_dir($outputDir);

sub list_dir {
        my @dirs = @_;
        my @files;
        find({ wanted => sub { push @files, glob "\"$_/*.txt\"" } , no_chdir => 1 }, @dirs);
        return @files;
}


0 commentaires