Schrift
[thread]7361[/thread]

Subroutine & Arrays: Funktion zur Arrayerzeugung



<< |< 1 2 >| >> 12 Einträge, 2 Seiten
Kristop8
 2005-10-17 15:57
#58938 #58938
User since
2005-10-06
22 Artikel
BenutzerIn
[default_avatar]
Hallo Leute,

ich versuche, leider bisher vergebns ein Programm zu basteln welches mir einen Bestimmten Ordner (c:\TEST) durchsucht und den Inhalt (Datein + Ordner) in ein Array speichert.

Falls aber der Ordner (c:\TEST) jedoch unterorner hat, soll das Programm in diese springe und den Inhalt dieses Orners (c:\TEST\LEVEL2 ) auch in ein (anderes) Array ausgeben. Dies soll er solange machen bis er alle Unterordner durchsucht sind.

Meine bisherigen Erungenschaften sind mager:

...
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use strict;
use warnings;
my $dir = "c:/test";
my @array;

GetDirs($dir);

sub GetDirs {
my ($directory) = @_;
opendir(DIR, $directory) or die "Error: couldn't open directory '$directory': $\n";
foreach my $entry (readdir(DIR))
{  
push (@array, $entry);
}
close (DIR);
} #End GetDirs

print "@array";


jetzt komme ich aber nicht so richtig weiter...

Die wichtigste Frage wäre jetzt wie kann man Arrays in sub-funktionen erstellen und diese dann immer mit deuen Namen versehen...

oder besser ausgedrückt wie übersetzt man folgenden Algorithmus in brauchbaren Code:

Code: (dl )
1
2
3
4
5
6
7
8
SUB_STRUCT
 SPRINGE IN ORDNER
 FALLS ORDNER LEER -> ENDE
 SONST ERSTELLE ARRAY
           SCHREIBE ALLE DATEINAMEN UND ORDNERNAMEN IN ARRAY
 STARTE SUB_STRUCT

ENDE SUB


Hoffe Ihr könnt mir etwas Denkhilfe geben.

LG Chris

edit pq: code-tags statt quote-tags\n\n

<!--EDIT|pq|1129562621-->
esskar
 2005-10-17 16:27
#58939 #58939
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
use strict;
use warnings;

my $dir = "c:/test";
my @array;

GetDirs($dir, \@array);

sub GetDirs {
  my ($directory, $arrayref) = @_;

  $directory =~ s!\\!/!g;
  $directory =~ s!/$!!;
 
  if(opendir(my $dir, $directory)) {
     while(my %entry = readdir $dir) {
         next if $entry =~ m!^\.\.$?!;
         
         my $path = "$directory/$entry";
         push @{$arrayref}, $path;
         GetDirs($path, $arrayref) if-d $path;
     }
     closedir $dir;
}
} #End GetDirs

print join("\n", @array);


ungetestet!\n\n

<!--EDIT|esskar|1129552114-->
Kristop8
 2005-10-17 17:28
#58940 #58940
User since
2005-10-06
22 Artikel
BenutzerIn
[default_avatar]
Hi, erstmal danke für deine Mühen,

kriege den Code aber nicht so richtig zum laufen...
  well ich aber    
 $directory =~ s!\\!/!g;
 $directory =~ s!/$!!;

auskommentiere kann ich das programm zwar starten, aber der output ist nicht der gewünschte....
-Kannst du bitte erklären was die die oberen zeilen eigenltich machen??
kannst du bitte erklären was:
  $directory =~ s!\\!/!g;
 $directory =~ s!/$!!;


und sollte es eigentlich bei opendir nicht heißen opendir (DIR, $dir) ...

macht?

und mit der zeile -> push @{$arrayref}, $path; <-
legst du doch die neu gefundenen einträge auf @array und erstellst nicht immer neue arrays, so wie ich es eigentlich vorgesehen hatte.

Hoffe habe mich selber jetzt nicht zu sehr verzetelt.  :rock:

LG Chris

edit pq: tt-tags hinzugefügt\n\n

<!--EDIT|pq|1129562681-->
Strat
 2005-10-17 19:36
#58941 #58941
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
1. was kommen denn fuer fehler, wenn du die $directory-Zeilen nicht auskommentierst? Ohne Fehlermeldung ist es ziemlich schwer, dir zu helfen.

2. $directory =~ s!\\!/!g; ersetzt in $directory alle \ durch /

3. $directory =~ s!/$!!; ersetzt am Ende ($) von Directory den / durch nichts, also wirft den Slash am Ende weg (esskar verwendet anstelle des "ueblichen" Separators fuer regulaere Ausdruecke / einfach ! , damit er den / im Ersetzungsteil nicht escapen muss. aber da koennte genausogut $directory =~ s/\/$//; stehen.

4. opendir (DIR, $dir) ... geht natuerlich; allerdings kann man z.B. DIR nur unschoen an Subroutinen uebergeben. Bei neueren Perl-Versionen (ich glaube, ab perl5) kann man anstelle des FH-Globs auch eine ganz normale variable verwenden, also opendir($dir, $directory); und da $dir das erste Mal vorkommt, deklariert sie esskar gleich mit my.

5. push @{$arrayref}, $path; da hast du recht

Mal eine Frage: wieso willst du die Dateien in separaten Arrays haben? da bekommst du probleme mit der erweiterbarkeit deines scriptes (wenn ein neues verzeichnis hinzukommt, musst du ein neues array erstellen, oder mit mehrdimensionalen Arrays arbeiten; aber auch dort musst du dir vermutlich merken, von wo die Dateien kommen).

Ist es nicht einfacher, alleDateiname inkl. Pfad in einem grossen Array zu speichern und dann damit zu arbeiten? Wenn du sowas willst, hilft dir vielleicht das Modul File::Find weiter, z.B.
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#! /usr/bin/perl
use strict;
use warnings;
use File::Find;

my $dir = "c:/test";
my @files = ();
find (sub {
if (-f $_) {
push (@files, $File::Find::name);
}
}, $dir);

foreach my $file (sort @files) {
print "Datei: $file\n";
} # foreach


Lesematerial:
perldoc File::Find
perldoc -f -f
(einfach in die Shell eingeben, und abwarten, was passiert)\n\n

<!--EDIT|Strat|1129563413-->
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
Kristop8
 2005-10-17 19:47
#58942 #58942
User since
2005-10-06
22 Artikel
BenutzerIn
[default_avatar]
Hi,

habe in der zwischenzeit auch File::Find auch ausprobiert ich kann dann alles in ein array schmeißen aber mehrere arrays sind nicht drinnen...

Der Grund warum ich mehrere Arrays anlegen will ist sehr subjektiv... und zwar will ich als oberziel die Datein und verzeichnisse in einer art explorerfester (später in HTML) ausgeben.

Auf der (web)site soll gelistet sein welche Ornder und datein Der root Ordner enthält....
und um den Überblick nicht zu verlieren, war meine Idee, einfach arrays anzulegen in denen ich den Inhalt(Besser die Namen des Inhalts) eines bestimmten Verzeichnisses abspeichere um dann ausgebe.

Villeicht gibt es auch eine bessere Methode...
in der Hinsicht bin ich ganz offen..

LG Chris
lichtkind
 2005-10-17 20:27
#58943 #58943
User since
2004-03-22
5680 Artikel
ModeratorIn + EditorIn
[Homepage]
user image
versuchs doch mit hashes und HoH und etwas mehr das rekursiv aufzuziehen dann müsste es doch gehen.
da würde fast deine getDir sub reichen sie müsste sich dann nur selbst aufrufen wenn sie ein unterverzeichnis rankommt. dar hash hat nicht nur den vorteil das als key der name und als value die ref für das subdir wäre bei files kannst danna auch hash von eigenschaften reinhängen. (so würde ich es wohl machen.)
Wiki:Tutorien in der Wiki, mein zeug:
kephra, baumhaus, garten, gezwitscher

Es beginnt immer mit einer Entscheidung.
smallish
 2005-10-17 21:18
#58944 #58944
User since
2005-10-13
28 Artikel
BenutzerIn
[default_avatar]
Du kannst es auch mit einem Hash machen:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
use strict;
use warnings;

my $tree = {};
read_it('D:', $tree);

{
my $durchlauf;
sub read_it {
my ($dir, $tree) = @_;

my $name;
$name = (split(/\\/, $dir))[-1] if ($durchlauf);
$name = $dir unless ($durchlauf);
$durchlauf = 1;

my @file = ();
my @dir = ();

opendir(VERZ, $dir);
while (my $read = readdir(VERZ)) {
if (-d "$dir\\$read") {
push (@dir, "$dir\\$read") if ($read !~ /(\.)$/);
}
else {
push @file, $read;
}
}
closedir(VERZ);

$tree -> {$name} = { files => \@file };

foreach my $directory (@dir) {
read_it("$directory", \%{ $tree -> {$name} })
}
}
}

Nun kannst du die Files von jedem Verzeichniss mittels
@{ $tree{'D:'}-> {perlbsp} -> {files} } aufrufen
beinhaltet nur die Dateien aus D:/perlbsp ohne ordner
oder
print "$_\n" foreach @{ $tree{'D:'} -> {hello} -> {web} -> {files}
gibt die Dateien aus D:/hello/web aus

EDIT: Die einzahl von directories schreibt man nunmal mit y...\n\n

<!--EDIT|smallish|1129569621-->
renee
 2005-10-18 00:37
#58945 #58945
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Man kann ja auch in der Subroutine mit CPAN:File::Find die Einträge in unterschiedliche Arrays packen...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Kristop8
 2005-10-19 13:43
#58946 #58946
User since
2005-10-06
22 Artikel
BenutzerIn
[default_avatar]
Hallo Leute,

danke für eueren input, vorallem der Code von smallish, scheit genau das zu machen was ich brauche... (so weit ich ihn verstanden habe)...

es gibt jedoch paar zeilen in seinem code deren funktion ich nicht so richtig verstehe...

z.B. die Zeile
Quote
$tree -> {$name} = { files => \@files };


so wie ich diese zeile verstehe, passiert da folgendes...
im Hash $tree wird dem Schlüssel $name ein "Pointer" auf das Array files zugewiesen... Stimmt das???

und dann bleiben noch die fragen, wie z.B.

Wie kann ich z.B. alle Verzeichnisse, bzw alle Datein, bzw beides eines Bestimmten Ordner ausgeben....

Besten Dank und LG

Chris
pKai
 2005-10-19 15:49
#58947 #58947
User since
2005-02-18
357 Artikel
BenutzerIn
[default_avatar]
[quote=Kristop8,19.Oct..2005, 11:43]
Code: (dl )
 $tree -> {$name} = { files => \@files };


so wie ich diese zeile verstehe, passiert da folgendes...
im Hash $tree wird dem Schlüssel $name ein "Pointer" auf das Array files zugewiesen... Stimmt das???[/quote]
im Hash $tree wird dem Schlüssel $name ein "Pointer" (=eine Referenz) auf ein (anonymes) Hash mit einem Schlüssel "files", und dem Wert einer Refrenz auf das Array @files zugewiesen

Quote
Wie kann ich z.B. alle Verzeichnisse, bzw alle Datein, bzw beides eines Bestimmten Ordner ausgeben....

perldoc perldsc
I sense a soul in search of answers.
<< |< 1 2 >| >> 12 Einträge, 2 Seiten



View all threads created 2005-10-17 15:57.