Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Тема в фак


Автор: Secandr 20.7.2004, 09:13
подскажите, что сделать, что бы работала рекурсия в перле?
Код
#!/usr/bin/perl
print "!!";
open PL,'>pl.txt' or die "file pl.txt not open";

read_dir("/home");

sub read_dir(){
   my $n,$t;
   my $name= shift;
   opendir dr, $name;
   while ($n=readdir(dr))
{
if (-f "$name/$n")
    {
    $t="$name/$n\n";
    print PL "$t";
    }
elsif ( ($n ne '.')and($n ne '..'))
    {
    read_dir("$name/$n");
    }
}
   closedir dr;
}
close PL;

Добавлено @ 09:14
Вот код без рекурсии, работает вполне великолепно:
Код
#!/usr/bin/perl
print "!!";
@dir=("/home");
open PL,'>pl.txt' or die "file pl.txt not open";

while ($name= shift @dir)
   {
   opendir dr, $name;
   while ($n=readdir(dr))
{
if (-f "$name/$n")
    {
    $t="$name/$n\n";
    print PL "$t";
    }
    }
elsif ( ($n ne '.')and($n ne '..'))
    {
    push @dir,"$name/$n";
    }
}
   closedir dr;
   }
close PL;

Добавлено @ 09:15
сразу убъю двух зайцев - напишу про рекурсию и про работу с деррикториями.

Автор: dimes 20.7.2004, 09:30
my $h;
opendir ($h,"dir");
........
либо
local *h;
opendir (h,"dir");
.......

Автор: Secandr 20.7.2004, 09:33
dimes
спасибо.

Автор: y0sh1 26.8.2004, 10:55
Проблема: надо написать скрипт на перле, который:
- в данной директории показывает список папок в ней (только в ней - во влженных не надо) и их размер (соответственно с подпапками считать);
- показывал бы тоже самое, но только размер файлов (во всей папке с подпапками) считал бы не для всех файлов, а только по заданной маски - например выдать размер всех файлов *.doc каждой подпапки в данной папке.
Сам в перле начинающий... надыбал скрипт на форуме, видоизменил (пока только для 1-го случая) - но что-то не пашет:

Код:
Код

#! perl -w
use strict;
sub dir_ls {
       my $save_dir;
       my $root = shift;
       local *DIR_LS;

       opendir DIR_LS ,$root;

       while (my $file = readdir (DIR_LS) ) {
              next if $file =~ /^\.\.?$/;
              print "$root/$file\n";
              if (-d "$root/$file") {
                  $count_d++;
                  dir_ls ("$root/$file");
              } else {
                  $dir_size += (stat("$root/$file"))[7];
                  $count_f++;
print "$count_f";
              }
       }
print "\n\nTotal -\nDirs: $count_d\nFiles: $count_f\nSize: $dir_size\n";
}

opendir FDIR, ".";
while($nm = readdir FDIR){
next if ($nm eq ".");
next if ($nm eq "..");

$stat     = 0;
$count_f  = 0;
$count_d  = 0;
$dir_size = 0;
    dir_ls ($nm);  
}
closedir FDIR;


типа пишет : "Global symbol "$count_d" requires explicit package name" для всех переменных - что не так!? Наск я понимаю переменную не определил!? Заранее спасибо, если кто поможет.... ну а если посоветуют ещё и конструкцию для 2-го варианта (чтобы размер файлов по маске считал0 - то будет вообще счастье! Зараенее спасибо!

Автор: korob2001 26.8.2004, 11:32
В одном топике, один вопрос. Это правила форума. Попробуй этот код.
Код

#!/usr/bin/perl

use strict;
my( $count_d, $dir_size, $count_f, $stat, $ed );
$ed = 'byte';
sub dir_ls {
      my $save_dir;
      my $root = shift;
      local *DIR_LS;

      opendir DIR_LS ,$root;

      while (my $file = readdir (DIR_LS) ) {
             next if $file =~ /^\.\.?$/;
             print "$root/$file\n";
             if (-d "$root/$file") {
                 $count_d++;
                 dir_ls ("$root/$file");
             } else {
                 $dir_size += (stat("$root/$file"))[7];
                 $count_f++;
                 print "$count_f";
             }
      }

  if ( $dir_size > 1024 ) {
       $dir_size = sprintf("%.1f", $dir_size / 1024 );
       $ed = 'KB';
  }

  if ( $dir_size > 1024 ) {
       $dir_size = sprintf("%.1f", $dir_size / 1024 );
       $ed = 'MB';
  }
 print "\n\nTotal -\nDirs: $count_d\nFiles: $count_f\nSize: ${dir_size} $ed\n";
 print "-" x 80, "\n";
}

opendir FDIR, ".";
while( my $nm = readdir FDIR){
          next if ($nm eq ".");
          next if ($nm eq "..");

          $stat     = 0;
          $count_f  = 0;
          $count_d  = 0;
          $dir_size = 0;
          dir_ls ($nm);
}
closedir FDIR;

Удачи.

Автор: y0sh1 26.8.2004, 12:48
Вобщем после дня эксперементов наваял я довольно простенький (и наверно всё же кривоватый) скрипт:
Код

use strict;

my $s_root   = '';
my $dir_size = 0;
my $file_size = 0;
my $t_dir_size = 0;
my $dir_name = '';

sub dir_ls {
       my $save_dir;
       my $root = shift;
       local *DIR_LS;

       opendir DIR_LS ,$root;

       while (my $file = readdir (DIR_LS) ) {
  next if $file =~ /^\.\.?$/;
  next if $root =~ /^\.\.?$/;
              if (-d "$root/$file") {
                  dir_ls ("$root/$file");
              } else {
                  $dir_size += (stat("$root/$file"))[7];
              }
       }
 #print "$s_root : $dir_size\n";
}
$dir_name="e:\\111";
chdir($dir_name);
opendir(D,$dir_name);
while($s_root=readdir(D)) {
if (-d "$s_root") {
 dir_ls ($s_root);
 print "$s_root : $dir_size\n";
 $t_dir_size += $dir_size;
 }
else {
 $file_size += (stat("$s_root"))[7];
 }
$dir_size = 0;
}
closedir(D);
print "Files in root directory: $file_size\n";
$t_dir_size += $file_size;
print "\nTotal: $t_dir_size\n";

Он проходит по заданной папке и выводит объём всех подпапок + отдельно объём файлов в корне указаной папки... Теперь решил прикрутить помимо подсчёта объёма всей подпапки ещё и объём файлов в ней по маске - например *.mp3 - по предложеной на форуме кнструкции:
Код
my $size = 0;
$size += (stat($_))[7] for (glob('e:/111/*.mp3'));
print "Size *.mp3 - $size bite";

Соответственно в скрипт написанный выше добавил:

Код

................
              } else {
                  $dir_size += (stat("$root/$file"))[7];
   $dir_size_mp3 += (stat("$root/$file"))[7] for (glob("$root/$file/*.mp3"));
              }
       }
 #print "$s_root : $dir_size\n";
}

...............

 [b]print "MP3 in: $dir_size_mp3\n\n";[/b]


Но что-то не катит... просто записывает в $dir_size_mp3 какое-то число... !?!?!? В чём может быть дело!?

Автор: ElectricalStorm 29.8.2004, 18:12
Код

1.

@list = <*.c>;
@list = glob("*.c");
You can also use readdir to extract the filenames manually:

или

opendir(DIR, $path);
@files = grep { /\.c$/ } readdir(DIR);
closedir(DIR);


2.  Для рекурсивных обходом директорий используйте File::Find

@ARGV = qw(.) unless @ARGV;
use File::Find;
find sub { print $File::Find::name, -d && "/", "\n" }, @ARGV;

3.

use File::Find;
@ARGV = (".") unless @ARGV;
my $sum = 0;
find sub { $sum += -s }, @ARGV;
print "@ARGV contains $sum bytes\n";



читаем CookBook smile.gif



Автор: y0sh1 30.8.2004, 12:39
Как при рекурсивном просмотре директорий более наглядно сделать "индикатор хода работы" так сказать - ну что бы видно было что процес идёт... в своём "сканере" пока сделал так:
Код
  if ($cc == 10){
     print "$root/$file\n";
     $cc = 0;
     }

те типа выводится на консоль каждая 10 папка\файл (все выводить слишком много)... причём на новой строке, думал прикрутить на одной:
Код
  if ($cc == 10){
     print "$root/$file[b]\r[/b]";
     $cc = 0;
     }

но в таком варианте что-то совсем ничего не вырисовывалось...
Может у кого есть более удачные варианты реализации !?

Автор: Secandr 30.8.2004, 12:45
Код
$cc++
  if ($cc == 10){
    print "$root/$file[b]\r[/b]";
    $cc = 0;
    }

Автор: y0sh1 30.8.2004, 13:22
Secandr
прости не совсем понял...
\r - это я хотел выделить... код конечно:
Код
$cc++
 if ($cc == 10){
   print "$root/$file\r";
   $cc = 0;
   }

Автор: Secandr 30.8.2004, 13:31
вообще лучше писать что-то типа \r\n или <br> если в хтмл.

А вообще один топик - один вопрос

Автор: y0sh1 30.8.2004, 13:37
Secandr
Цитата
вообще лучше писать что-то типа \r\n

типа это выведет список всех поддир и файлов в одной строке!?

Цитата
А вообще один топик - один вопрос

те если вопрос в русле уже созданой темы, то всё равно надо открывать новую!?

Автор: Secandr 30.8.2004, 13:46
тема была не про то как читать дирректорию, а про то как превратить глобальный указатель в локальный!
Добавлено @ 13:47
P.S. Открывай новый топик и подробно опиши проблему.

Автор: y0sh1 30.8.2004, 14:10
Secandr
сорри если не туда запости, но искал по описанию темы, а там сказано чётко:
Цитата
Хочу написать о рекурсии
- у меня тоже рекурсия... и индикатор нужен... sad.gif

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)