[31457] in Perl-Users-Digest
Perl-Users Digest, Issue: 2709 Volume: 11
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Mon Dec 7 21:09:39 2009
Date: Mon, 7 Dec 2009 18:09:06 -0800 (PST)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Mon, 7 Dec 2009 Volume: 11 Number: 2709
Today's topics:
File::Temp help (hymie!)
Re: File::Temp help (hymie!)
Re: File::Temp help <ben@morrow.me.uk>
Re: File::Temp help <tadmc@seesig.invalid>
Finding expiration date of cookie <jwcarlton@gmail.com>
How do i get the drive letter ? (need win32::ole assist <wolf@gsheep.com>
Re: How do i get the drive letter ? (need win32::ole as <ben@morrow.me.uk>
Re: How do i get the drive letter ? (need win32::ole as <wolf@gsheep.com>
Re: How to add system user accounts with perl? <smallpond@juno.com>
Re: How to add system user accounts with perl? <sysadmin@example.com>
translating an OS directory recursively into a tree obj <mathematisch@gmail.com>
Re: translating an OS directory recursively into a tree <ben@morrow.me.uk>
Re: translating an OS directory recursively into a tree <mathematisch@gmail.com>
Re: translating an OS directory recursively into a tree <tadmc@seesig.invalid>
Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Mon, 07 Dec 2009 19:07:29 GMT
From: hymie@lactose.homelinux.net (hymie!)
Subject: File::Temp help
Message-Id: <RncTm.35721$kY2.19073@newsfe01.iad>
Greetings.
I must be missing something. I hope somebody can tell me what it is.
Short question:
I'm trying to use a temporary file. However,
my $fh = tempfile();
while (<FILE>)
{
print $fh $_;
}
only results in an empty file.
Long question:
According to the perldoc for File::Temp
tmpfile
Returns the filehandle of a temporary file.
$fh = tmpfile();
Now, I was under the impression that "the filehandle of a temporarly file"
is an incomplete concept -- that part of the definition of a filehandle
includes whether the file is open for reading or writing. So I'm not I
understand exactly what is being returned from the tempfile() command,
or how I can use it to write data into a temporary file.
Can somebody enlighten me?
Thanks.
--hymie! http://lactose.homelinux.net/~hymie hymie@lactose.homelinux.net
-------------------------------------------------------------------------------
------------------------------
Date: Mon, 07 Dec 2009 19:24:21 GMT
From: hymie@lactose.homelinux.net (hymie!)
Subject: Re: File::Temp help
Message-Id: <FDcTm.66741$rE5.12607@newsfe08.iad>
Naturally, as soon as I've decided I've searched everything I know,
and post a question to the newsgroup, then the next link I stumble over
has the answer.
In our last episode, the evil Dr. Lacto had captured our hero,
hymie@lactose.homelinux.net (hymie!), who said:
>my $fh = tempfile();
>while (<FILE>)
>{
> print $fh $_;
>}
close ($fh);
Duh.
--hymie! http://lactose.homelinux.net/~hymie hymie@lactose.homelinux.net
-------------------------------------------------------------------------------
------------------------------
Date: Mon, 7 Dec 2009 20:22:45 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: File::Temp help
Message-Id: <lp40v6-lnc.ln1@osiris.mauzo.dyndns.org>
Quoth hymie@lactose.homelinux.net (hymie!):
> Greetings.
>
> I must be missing something. I hope somebody can tell me what it is.
>
> Short question:
>
> I'm trying to use a temporary file. However,
>
> my $fh = tempfile();
> while (<FILE>)
> {
> print $fh $_;
> }
>
> only results in an empty file.
Files created with tempfile will normally be deleted when the process
exits, or under some systems as soon as the file is closed. How are you
discovering the file is empty? You don't ask File::Temp for the
filename...
> Long question:
>
> According to the perldoc for File::Temp
>
> tmpfile
> Returns the filehandle of a temporary file.
> $fh = tmpfile();
>
> Now, I was under the impression that "the filehandle of a temporarly file"
> is an incomplete concept -- that part of the definition of a filehandle
> includes whether the file is open for reading or writing. So I'm not I
> understand exactly what is being returned from the tempfile() command,
> or how I can use it to write data into a temporary file.
tempfile returns a handle open for both reading and writing. In Perl
terms, the file is opened with the "<+" mode.
Ben
------------------------------
Date: Mon, 07 Dec 2009 14:56:16 -0600
From: Tad McClellan <tadmc@seesig.invalid>
Subject: Re: File::Temp help
Message-Id: <slrnhhqqpe.2kp.tadmc@tadbox.sbcglobal.net>
hymie! <hymie@lactose.homelinux.net> wrote:
> Naturally, as soon as I've decided I've searched everything I know,
> and post a question to the newsgroup, then the next link I stumble over
> has the answer.
>
> In our last episode, the evil Dr. Lacto had captured our hero,
> hymie@lactose.homelinux.net (hymie!), who said:
>
>>my $fh = tempfile();
>>while (<FILE>)
>>{
>> print $fh $_;
>>}
>
> close ($fh);
>
> Duh.
sounds like you were:
Suffering from Buffering
http://perl.plover.com/FAQs/Buffering.html
--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
------------------------------
Date: Mon, 7 Dec 2009 17:27:06 -0800 (PST)
From: Jason Carlton <jwcarlton@gmail.com>
Subject: Finding expiration date of cookie
Message-Id: <9caa443d-e14b-47d7-98c0-350d23c3ef87@j19g2000yqk.googlegroups.com>
Is there any way to find the expiration date of a set cookie?
I'm setting a cookie in one script, and the expiration date is set
dynamically. In another script, I want to set another cookie, and want
to match the expiration date to the one set in the earlier script.
TIA,
Jason
------------------------------
Date: Mon, 07 Dec 2009 16:55:51 +0100
From: wolf <wolf@gsheep.com>
Subject: How do i get the drive letter ? (need win32::ole assistance)
Message-Id: <hfj8ia$mmi$00$1@news.t-online.com>
Hello,
i'm trying to battle my way through the following problem:
a) I need to get a list of all PHYSICAL drives on a machine. (got that)
b) I need to get a list of all PARTITIONS on each PHYSICAL drive. (got that)
c) I need to know which partition is assigned which drive letter (if at
all) and i have no idea how to do this.
This is surely due to my lack of OLE understanding.
Can someone point me the way?
the perl code to get answers to a) and b) is below (found it in a forum).
Cheers, Wolf
------------------
#!/usr/bin/perl
#---------------------------------------------------------------------
# di.pl - Disk ID tool
# This script is intended to assist investigators in identifying disks
# attached to systems. It can be used by an investigator to document
# a disk following acquisition, providing information for use in
# acquisition worksheets and chain-of-custody documentation.
#
# This tool may also be run remotely against managed system, by passing
# the necessary arguments at the command line.
#
# Usage: di.pl
# di.pl <system> <username> <password>
#
# copyright 2006 H. Carvey, keydet89@yahoo.com
#---------------------------------------------------------------------
use strict;
use Win32::OLE qw(in);
my $server = shift || Win32::NodeName();
my $user = shift || "";
my $pwd = shift || "";
my $locatorObj = Win32::OLE->new('WbemScripting.SWbemLocator') || die
"Error creating locator object: ".Win32::OLE->LastError()."\n";
$locatorObj->{Security_}->{impersonationlevel} = 3;
my $serverObj = $locatorObj->ConnectServer($server,'root\cimv2',$user,$pwd)
|| die "Error connecting to $server: ".Win32::OLE->LastError()."\n";
my %capab = (0 => "Unknown",
1 => "Other",
2 => "Sequential Access",
3 => "Random Access",
4 => "Supports Writing",
5 => "Encryption",
6 => "Compression",
7 => "Supports Removable Media",
8 => "Manual Cleaning",
9 => "Automatic Cleaning",
10 => "SMART Notification",
11 => "Supports Dual Sided Media",
12 => "Ejection Prior to Drive Dismount Not Required");
my %disk = ();
foreach my $drive (in $serverObj->InstancesOf("Win32_DiskDrive")) {
$disk{$drive->{Index}}{DeviceID} = $drive->{DeviceID};
$disk{$drive->{Index}}{Manufacturer} = $drive->{Manufacturer};
$disk{$drive->{Index}}{Model} = $drive->{Model};
$disk{$drive->{Index}}{InterfaceType} = $drive->{InterfaceType};
$disk{$drive->{Index}}{MediaType} = $drive->{MediaType};
$disk{$drive->{Index}}{Partitions} = $drive->{Partitions};
# The drive signature is a DWORD value written to offset 0x1b8 (440) in
the MFT
# when the drive is formatted. This value can be used to identify a
specific HDD,
# either internal/fixed or USB/external, by corresponding the signature
to the
# values found in the MountedDevices key of the Registry
$disk{$drive->{Index}}{Signature} = $drive->{Signature};
$disk{$drive->{Index}}{Size} = $drive->{Size};
$disk{$drive->{Index}}{Capabilities} = $drive->{Capabilities};
}
my %diskpart = ();
foreach my $part (in $serverObj->InstancesOf("Win32_DiskPartition")) {
$diskpart{$part->{DiskIndex}.":".$part->{Index}}{DeviceID} =
$part->{DeviceID};
$diskpart{$part->{DiskIndex}.":".$part->{Index}}{Bootable} = 1 if
($part->{Bootable});
$diskpart{$part->{DiskIndex}.":".$part->{Index}}{BootPartition} = 1 if
($part->{BootPartition});
$diskpart{$part->{DiskIndex}.":".$part->{Index}}{PrimaryPartition} = 1
if ($part->{PrimaryPartition});
$diskpart{$part->{DiskIndex}.":".$part->{Index}}{Type} = $part->{Type};
}
my %media = ();
foreach my $pm (in $serverObj->InstancesOf("Win32_PhysicalMedia")) {
$media{$pm->{Tag}} = $pm->{SerialNumber};
}
foreach my $dd (sort keys %disk) {
print "DeviceID : ".$disk{$dd}{DeviceID}."\n";
print "Model : ".$disk{$dd}{Model}."\n";
print "Interface : ".$disk{$dd}{InterfaceType}."\n";
print "Media : ".$disk{$dd}{MediaType}."\n";
print "Capabilities : \n";
foreach my $c (in $disk{$dd}{Capabilities}) {
print "\t".$capab{$c}."\n";
}
my $sig = $disk{$dd}{Signature};
$sig = "<None>" if ($sig == 0x0);
printf "Signature : 0x%x\n",$sig;
my $sn = $media{$disk{$dd}{DeviceID}};
print "Serial No : $sn\n";
print "\n";
print $disk{$dd}{DeviceID}." Partition Info : \n";
my $part = $disk{$dd}{Partitions};
foreach my $p (0..($part - 1)) {
my $partition = $dd.":".$p;
print "\t".$diskpart{$partition}{DeviceID}."\n";
print "\t".$diskpart{$partition}{Type}."\n";
print "\t\tBootable\n" if ($diskpart{$partition}{Bootable});
print "\t\tBoot Partition\n" if ($diskpart{$partition}{BootPartition});
print "\t\tPrimary Partition\n" if
($diskpart{$partition}{PrimaryPartition});
print "\n";
#foreach my $x (keys %{$diskpart{$partition}}) {
# print 'Key: '.$x.' = '.$diskpart{$partition}{$x}."\n";
#}
}
}
----------
output on my machine: (excerpt)
----------
DeviceID : \\.\PHYSICALDRIVE2
Model : SAMSUNG HD321KJ
Interface : IDE
Media : Fixed hard disk media
Capabilities :
Random Access
Supports Writing
Signature : 0xe6e5e6e5
Serial No : 30535055314a504e303932303033202020202020
\\.\PHYSICALDRIVE2 Partition Info :
Disk #2, Partition #0
Installable File System
Bootable
Boot Partition
Primary Partition
Disk #2, Partition #1
Installable File System
Primary Partition
Disk #2, Partition #2
Installable File System
Primary Partition
Disk #2, Partition #3
Extended Partition
------------------------------
Date: Mon, 7 Dec 2009 16:18:33 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: How do i get the drive letter ? (need win32::ole assistance)
Message-Id: <pfmvu6-d7u2.ln1@osiris.mauzo.dyndns.org>
Quoth wolf <wolf@gsheep.com>:
>
> a) I need to get a list of all PHYSICAL drives on a machine. (got that)
> b) I need to get a list of all PARTITIONS on each PHYSICAL drive. (got that)
>
> c) I need to know which partition is assigned which drive letter (if at
> all) and i have no idea how to do this.
>
> This is surely due to my lack of OLE understanding.
> Can someone point me the way?
You will need to look up the documentation for whatever a
WbemScripting.SWbemLocator is. This has nothing to do with Perl, or
Win32::OLE: it it just passing the method calls through to the OLE
object, so you need that documentation. Try searching on
http://msdn.microsoft.com/.
<snip>
> foreach my $drive (in $serverObj->InstancesOf("Win32_DiskDrive")) {
> $disk{$drive->{Index}}{DeviceID} = $drive->{DeviceID};
> $disk{$drive->{Index}}{Manufacturer} = $drive->{Manufacturer};
> $disk{$drive->{Index}}{Model} = $drive->{Model};
> $disk{$drive->{Index}}{InterfaceType} = $drive->{InterfaceType};
> $disk{$drive->{Index}}{MediaType} = $drive->{MediaType};
> $disk{$drive->{Index}}{Partitions} = $drive->{Partitions};
This is very bad style. Factor out the deref into a variable, at least,
and I would put property-copying into a loop:
for my $drive (...) {
my $disk = $disk{$drive->{Index}};
$disk->{$_} = $drive->{$_} for qw{
DeviceID
Manufacturer
Model
InterfaceType
MediaType
Partitions
Signature
Size
Capabilities
};
assuming you can't simply assign
$disk{$drive->{Index}} = $drive;
(this is often a bad idea with OLE objects, because they end up not
being GCed soon enough). There is more of the same below.
<snip>
> foreach my $dd (sort keys %disk) {
> print "DeviceID : ".$disk{$dd}{DeviceID}."\n";
> print "Model : ".$disk{$dd}{Model}."\n";
> print "Interface : ".$disk{$dd}{InterfaceType}."\n";
> print "Media : ".$disk{$dd}{MediaType}."\n";
> print "Capabilities : \n";
Learn how to use heredocs, at the very least; better would be to use
Perl6::Form or TT or something to format the output decently.
for my $dd (sort keys %disk) {
my $disk = $disk{$dd};
print <<OUT;
DeviceID : $disk->{DeviceID}
Model : $disk->{Model}
Interface : $disk->{InterfaceType}
Media : $disk->{MediaType}
Capabilities :
OUT
}
Ben
------------------------------
Date: Mon, 07 Dec 2009 19:24:18 +0100
From: wolf <wolf@gsheep.com>
Subject: Re: How do i get the drive letter ? (need win32::ole assistance)
Message-Id: <hfjh8l$8fj$00$1@news.t-online.com>
Ben Morrow schrieb:
> Quoth wolf <wolf@gsheep.com>:
>> a) I need to get a list of all PHYSICAL drives on a machine. (got that)
>> b) I need to get a list of all PARTITIONS on each PHYSICAL drive. (got that)
>>
>> c) I need to know which partition is assigned which drive letter (if at
>> all) and i have no idea how to do this.
>>
>> This is surely due to my lack of OLE understanding.
>> Can someone point me the way?
>
> You will need to look up the documentation for whatever a
> WbemScripting.SWbemLocator is. This has nothing to do with Perl, or
> Win32::OLE: it it just passing the method calls through to the OLE
> object, so you need that documentation. Try searching on
> http://msdn.microsoft.com/.
>
> <snip>
>> foreach my $drive (in $serverObj->InstancesOf("Win32_DiskDrive")) {
>> $disk{$drive->{Index}}{DeviceID} = $drive->{DeviceID};
>> $disk{$drive->{Index}}{Manufacturer} = $drive->{Manufacturer};
>> $disk{$drive->{Index}}{Model} = $drive->{Model};
>> $disk{$drive->{Index}}{InterfaceType} = $drive->{InterfaceType};
>> $disk{$drive->{Index}}{MediaType} = $drive->{MediaType};
>> $disk{$drive->{Index}}{Partitions} = $drive->{Partitions};
>
> This is very bad style. Factor out the deref into a variable, at least,
> and I would put property-copying into a loop:
>
> for my $drive (...) {
> my $disk = $disk{$drive->{Index}};
>
> $disk->{$_} = $drive->{$_} for qw{
> DeviceID
> Manufacturer
> Model
> InterfaceType
> MediaType
> Partitions
> Signature
> Size
> Capabilities
> };
>
> assuming you can't simply assign
>
> $disk{$drive->{Index}} = $drive;
>
> (this is often a bad idea with OLE objects, because they end up not
> being GCed soon enough). There is more of the same below.
>
> <snip>
>> foreach my $dd (sort keys %disk) {
>> print "DeviceID : ".$disk{$dd}{DeviceID}."\n";
>> print "Model : ".$disk{$dd}{Model}."\n";
>> print "Interface : ".$disk{$dd}{InterfaceType}."\n";
>> print "Media : ".$disk{$dd}{MediaType}."\n";
>> print "Capabilities : \n";
>
> Learn how to use heredocs, at the very least; better would be to use
> Perl6::Form or TT or something to format the output decently.
>
> for my $dd (sort keys %disk) {
> my $disk = $disk{$dd};
>
> print <<OUT;
> DeviceID : $disk->{DeviceID}
> Model : $disk->{Model}
> Interface : $disk->{InterfaceType}
> Media : $disk->{MediaType}
> Capabilities :
> OUT
> }
>
> Ben
>
Thanks Ben, gonna try that.
Usually i cant find my own *ss on MS's website :/ but hey :) at least i
have a pointer.
I didnt like the perl style of the snippet either but at least it got me
some of the info needed. It looks a bit clumsy and overloaded with
print and if statements :p I basically passed it on without any changes,
except for trying it out - and it worked. I usually write my own code
once i understand the basic data retrieval, but alas i'm not there yet.
Cheers, Wolf
------------------------------
Date: Sun, 6 Dec 2009 19:31:29 -0800 (PST)
From: smallpond <smallpond@juno.com>
Subject: Re: How to add system user accounts with perl?
Message-Id: <ed99f76d-b45b-4f27-8bb3-c0ff4fbc07b5@g31g2000vbr.googlegroups.com>
On Dec 5, 8:21=A0pm, nobody <nob...@nowhere.com> wrote:
> I need to add numerous user accounts on a linux system. =A0I have a list =
of
> user names and passwords like:
>
> jsmith =A0 =A0 sesam3
> rjones =A0 =A0 abracadb
>
> Of course this is easy enough to create a hash from, but can perl be used
> to actually create an account, and set the password as well? =A0So the
> entire operation would be equivalent to:
>
> useradd -g somegroup -u someuid -c "jsmith" -s /bin/bash -m rjones
>
> passwd rjones
>
> I've been googling, but couldn't even find a script as a starting point.
>
> -Thanks
webmin is written in perl
------------------------------
Date: Mon, 07 Dec 2009 12:38:16 -0800
From: Wanna-Be Sys Admin <sysadmin@example.com>
Subject: Re: How to add system user accounts with perl?
Message-Id: <YIdTm.3092$ha3.153@newsfe19.iad>
Ben Morrow wrote:
>
> Quoth Wanna-Be Sys Admin <sysadmin@example.com>:
>> nobody wrote:
>>
>> > I need to add numerous user accounts on a linux system. I have a
>> > list
>>
>> Sure, you can use just about any language to do this. It's all about
>> parsing the info, checking it's okay, opening files, writing to them
>> (possibly in the right place, depending on what you're looking to
>> do), encrypt the password, creating directories, setting permissions
>> and
>> ownerships, etc. it can be very simple, it just depends on how many
>> things you need the new (adding) account to do. For the most part,
>> it's opening the passwd, group, etc. files, adding the info (after
>> determining the next highest uid/gid that's not taken (probably over
>> 500 as well)), and so on.
>
> Don't do that. There are more than a few subtleties to adding a new
> user, in particular: making sure the passwd file is updated
> atomically, being *certain* you've got the format right, regenerating
> any databases your system might use, and knowing when you actually
> need to update some other file entirely (like /etc/master.passwd on
> BSD). Getting any of this wrong is likely to cause serious problems
> with your system, so just use the provided tools.
>
> Ben
I was suggesting different methods, and said that you should likely use
the system tools. However, there's absolutely nothing wrong with
rolling out your own solution, provided you know what you're doing,
implement proper file locking, etc. But, the fact the OP asked, surely
means they don't know and if they use an existing script someone else
created, they may take the risk of using something that doesn't do what
they hope or need it to. But, the subtleties are simple enough to deal
with, provided there's the experience and knowledge of exactly what you
need to do, and how. That all said, with the OP's question, I would
agree they probably shouldn't try, at this point anyway.
--
Not really a wanna-be, but I don't know everything.
------------------------------
Date: Mon, 7 Dec 2009 02:43:10 -0800 (PST)
From: Mathematisch <mathematisch@gmail.com>
Subject: translating an OS directory recursively into a tree object
Message-Id: <bfe71719-031e-43c9-8faf-c0a748adc458@s19g2000vbm.googlegroups.com>
Hello,
Would someone please show how to create a tree data structure by using
an OS directory as input. So the nodes should be the names of the
directories and the leaves should represent each file. Each directory
should turn into a node and its files and sub directories will become
its children.
In this example, I have downloaded the Tree::Simple module from CPAN
and I know that Perl's File::Find module traverses a directory
recursively. I am stuck as I do not know how one can create a tree
object from the results of File::Find
Below is the code that I've tried on a directory with multiple sub
directories and files. It does not create the desired tree object:
#start of the failed code
use strict;
use warnings;
use File::Find;
use Tree::Simple;
use Data::Dumper;
my $tree = Tree::Simple->new("0", Tree::Simple->ROOT); #create the
root node
find(\&processCurrent, ('C:\PROJECTS\MyDir') ); #process all
directories and files
print Dumper $tree; #the desired tree is not created!
sub processCurrent {
if (-d) { #this is a directory
$tree = Tree::Simple->new($_, $tree); #create a new
subtree, take the last one as parent
}
elsif (-f) { #this is a file
$tree->addChild(Tree::Simple->new($_)); #add this file
to the current tree
}
}
#end of the failed code
------------------------------
Date: Mon, 7 Dec 2009 11:36:31 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: translating an OS directory recursively into a tree object
Message-Id: <vu5vu6-bgm2.ln1@osiris.mauzo.dyndns.org>
Quoth Mathematisch <mathematisch@gmail.com>:
> Hello,
>
> Would someone please show how to create a tree data structure by using
> an OS directory as input. So the nodes should be the names of the
> directories and the leaves should represent each file. Each directory
> should turn into a node and its files and sub directories will become
> its children.
>
> In this example, I have downloaded the Tree::Simple module from CPAN
> and I know that Perl's File::Find module traverses a directory
> recursively. I am stuck as I do not know how one can create a tree
> object from the results of File::Find
>
> Below is the code that I've tried on a directory with multiple sub
> directories and files. It does not create the desired tree object:
>
> #start of the failed code
> use strict;
> use warnings;
> use File::Find;
> use Tree::Simple;
> use Data::Dumper;
>
>
> my $tree = Tree::Simple->new("0", Tree::Simple->ROOT); #create the
> root node
> find(\&processCurrent, ('C:\PROJECTS\MyDir') ); #process all
> directories and files
In general it is better to use forward slashes for paths under Win32.
The only exceptions are paths that will be passed to cmd.exe (via system,
or otherwise) and paths that will be passed to native Win32 APIs like
CreateProcess.
> print Dumper $tree; #the desired tree is not created!
>
> sub processCurrent {
> if (-d) { #this is a directory
> $tree = Tree::Simple->new($_, $tree); #create a new
> subtree, take the last one as parent
This is your problem. You are setting $tree to the new subtree, but
you've then lost your handle on the parent tree. This means that when
File::Find moves up a level in the hierarchy the new nodes will be added
in the wrong place. One solution is to keep a stack of 'parents',
something like this:
my @parent = Tree::Simple->new("0");
find {
wanted => sub {
my $node = Tree::Simple->new($_);
$parent[-1]->addChild($node);
-d and push @parent, $node;
},
postprocess => sub {
pop @parent;
},
}, "C:/PROJECTS/MyDir";
This will leave you with the desired tree as the only remaining element
in @parent.
Ben
------------------------------
Date: Mon, 7 Dec 2009 05:31:05 -0800 (PST)
From: Mathematisch <mathematisch@gmail.com>
Subject: Re: translating an OS directory recursively into a tree object
Message-Id: <4589aa81-dc1f-488b-9224-32384ee6d01e@e27g2000yqd.googlegroups.com>
On Dec 7, 12:36=A0pm, Ben Morrow <b...@morrow.me.uk> wrote:
> Quoth Mathematisch <mathemati...@gmail.com>:
>
>
>
> > Hello,
>
> > Would someone please show how to create a tree data structure by using
> > an OS directory as input. So the nodes should be the names of the
> > directories and the leaves should represent each file. Each directory
> > should turn into a node and its files and sub directories will become
> > its children.
>
> > In this example, I have downloaded the Tree::Simple module from CPAN
> > and I know that Perl's File::Find module traverses a directory
> > recursively. I am stuck as I do not know how one can create a tree
> > object from the results of File::Find
>
> > Below is the code that I've tried on a directory with multiple sub
> > directories and files. It does not create the desired tree object:
>
> > #start of the failed code
> > use strict;
> > use warnings;
> > use File::Find;
> > use Tree::Simple;
> > use Data::Dumper;
>
> > my $tree =3D Tree::Simple->new("0", Tree::Simple->ROOT); #create the
> > root node
> > find(\&processCurrent, ('C:\PROJECTS\MyDir') ); #process all
> > directories and files
>
> In general it is better to use forward slashes for paths under Win32.
> The only exceptions are paths that will be passed to cmd.exe (via system,
> or otherwise) and paths that will be passed to native Win32 APIs like
> CreateProcess.
>
> > print Dumper $tree; #the desired tree is not created!
>
> > sub processCurrent {
> > =A0 =A0 if (-d) { =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 #this is =
a directory
> > =A0 =A0 =A0 =A0$tree =3D Tree::Simple->new($_, $tree); =A0 =A0 =A0 #cre=
ate a new
> > subtree, take the last one as parent
>
> This is your problem. You are setting $tree to the new subtree, but
> you've then lost your handle on the parent tree. This means that when
> File::Find moves up a level in the hierarchy the new nodes will be added
> in the wrong place. One solution is to keep a stack of 'parents',
> something like this:
>
> =A0 =A0 my @parent =3D Tree::Simple->new("0");
>
> =A0 =A0 find {
> =A0 =A0 =A0 =A0 wanted =3D> sub {
> =A0 =A0 =A0 =A0 =A0 =A0 my $node =3D Tree::Simple->new($_);
> =A0 =A0 =A0 =A0 =A0 =A0 $parent[-1]->addChild($node);
> =A0 =A0 =A0 =A0 =A0 =A0 -d and push @parent, $node;
> =A0 =A0 =A0 =A0 },
> =A0 =A0 =A0 =A0 postprocess =3D> sub {
> =A0 =A0 =A0 =A0 =A0 =A0 pop @parent;
> =A0 =A0 =A0 =A0 },
> =A0 =A0 }, "C:/PROJECTS/MyDir";
>
> This will leave you with the desired tree as the only remaining element
> in @parent.
>
> Ben
Ben, thanks a lot for the clarification.
After some further search, I have found a module extension which
parses a directory into a Tree::Simple object (i.e.:
http://search.cpan.org/~stevan/Tree-Simple-VisitorFactory-0.10/lib/Tree/Sim=
ple/Visitor/LoadDirectoryTree.pm)
It might be useful for other people having this issue.
Best regards
------------------------------
Date: Mon, 07 Dec 2009 08:31:06 -0600
From: Tad McClellan <tadmc@seesig.invalid>
Subject: Re: translating an OS directory recursively into a tree object
Message-Id: <slrnhhq479.17h.tadmc@tadbox.sbcglobal.net>
Mathematisch <mathematisch@gmail.com> wrote:
> Would someone please show how to create a tree data structure by using
> an OS directory as input.
This probably won't help you solve your problem, but whenever the
subject of parsing directory trees comes up, I just must share it.
Got this off the 'net over a decade ago...
find . -print | sed -e 's,[^/]*/\([^/]*\)$,`--\1,' -e 's,[^/]*/,| ,g'
Simply amazing.
--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
------------------------------
Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>
Administrivia:
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests.
#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V11 Issue 2709
***************************************