Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Directory Structure.

by Nansh (Acolyte)
on Mar 31, 2017 at 11:52 UTC ( [id://1186609]=perlquestion: print w/replies, xml ) Need Help??

Nansh has asked for the wisdom of the Perl Monks concerning the following question:

I want directory structure like this

VEHICLES->CARS

BIKES->

VEHICLES is a main directory CARS is a sub-directory and BIKES is also sub-directory of VEHICLES

we have CARS and BIKES in an array called @files

$dir= "VEHICLES"; mkdir ($dir); chdir ($dir); foreach $file(@files) { mkdir $file; chdir $file; chdir $dir; }
I am not able to create two sub-directory only one sub-directory is creating inside vehicles

EXAMPLE: VEHICLES->CARS. Bike is not creating inside VEHICLES

I tried alot but couldnt able to do that please help me to do that

Replies are listed 'Best First'.
Re: Directory Structure.
by GotToBTru (Prior) on Mar 31, 2017 at 12:53 UTC

    The problem is relative versus absolute paths. You create directory VEHICLES, move to it, and in the first loop you create directory CARS and then move to it. But the chdir $dir statement tries to move to VEHICLES->CARS->VEHICLES which of course doesn't work. You need to change the value in your chdir statement to an absolute path. Perhaps something like:

    use strict; use warnings; my @files=qw/CARS BIKES/; chomp(my $home = `pwd`); my $dir = 'VEHICLES'; mkdir ($dir); chdir ($dir); foreach my $file(@files) { mkdir $file; chdir $file; chdir "$home/$dir"; }

    See here if you aren't familiar with chomp.

    But God demonstrates His own love toward us, in that while we were yet sinners, Christ died for us. Romans 5:8 (NASB)

Re: Directory Structure.
by AppleFritter (Vicar) on Mar 31, 2017 at 12:03 UTC

    Use File::Path, a core module, which provides make_path. Also, map comes in handy here -- make_path can create several directories at once, so you can save the foreach:

    use File::Path qw/make_path/; # ... make_path map { "$dir/$_" } @files;
Re: Directory Structure.
by shmem (Chancellor) on Mar 31, 2017 at 13:19 UTC
    I tried alot but couldnt able to do that please help me to do that

    What you didn't try to do is describing your code to yourself; I'll do that for you:

    You create VEHICLES and change into this empty directory. Fine. Inside this directory you create a directory and change into this empty dirctory.

    Then, inside this subdirectory, you try to chdir into the directory VEHICLES (which is what the variable $dir holds). This subdirectory doesn't exist in VEHICLES/CARS. Bummer. This part of your code silently fails. Your current working directory stays the same (VEHICLES/CARS).

    You iterate to the next element in @files.
    You create the next directory, BIKES, and change directory into that. Again, you try to chdir into VEHICLES which doesn't exist.

    You end up with

    VEHICLES/CARS/BIKES

    which is your current working directory after the loop ends.

    First thing you should do is checking all your operations for success:

    $dir = "VEHICLES"; @files = ('CARS', 'BIKES'); mkdir ($dir) or die "can't mkdir $dir: $!"; chdir ($dir) or die "can't chdir to $dir: '$!'"; foreach $file(@files) { mkdir $file or die "(loop) can't mkdir $file: '$!'"; chdir $file or die "(loop) can't chdir to $file: '$!'"; chdir $dir or die "(loop) can't chdir to $dir: '$!'"; }

    Output:

    (loop) can't chdir to VEHICLES: 'No such file or directory' at try.pl +line 10.

    Aha! there's no such file or directory inside the loop, when you try to chdir to VEHICLES. You realize the two chdir statements inside the loop are bogus and eliminate them:

    $dir = "VEHICLES"; @files = ('CARS', 'BIKES'); mkdir ($dir) or die "can't mkdir $dir: $!"; chdir ($dir) or die "can't chdir to $dir: '$!'"; foreach $file(@files) { mkdir $file or die "(loop) can't mkdir $file: '$!'"; }

    Then you run your file again. Output now:

    can't mkdir VEHICLES: File exists at try.pl line 3.

    So, you should check for existence before making a directory. See -X for the various file testing operators.

    $dir = "VEHICLES"; @files = ('CARS', 'BIKES'); if(not -d $dir) { mkdir ($dir) or die "can't mkdir $dir: $!"; } chdir ($dir) or die "can't chdir to $dir: '$!'"; foreach $file(@files) { if (not -d $file) { mkdir $file or die "(loop) can't mkdir $file: '$!'"; } }

    Now your code runs and produces the expected structure:

    VEHICLES VEHICLES/BIKES VEHICLES/CARS

    See chdir, mkdir, not, -X, or, die for more information about the added bits.

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
Re: Directory Structure.
by hippo (Archbishop) on Mar 31, 2017 at 12:59 UTC
    chdir $file; chdir $dir;

    Can you explain the purpose of that?

    ISTM that your code has too many statments. Here's an SSCCE

    #!/usr/bin/env perl use strict; use warnings; use Test::More tests => 3; # Do all this in /tmp because we don't want permission trouble or to # pollute real dirs while testing chdir '/tmp'; my $dir = 'VEHICLES'; my @files = qw/CARS BIKES/; mkdir $dir; ok (-d $dir); chdir $dir; foreach my $subdir (@files) { mkdir $subdir; ok (-d $subdir); }

    Running gives:

    $ ./ex.pl
    1..3
    ok 1
    ok 2
    ok 3
    $ tree VEHICLES/
    VEHICLES/
    ├── BIKES
    └── CARS
    
    2 directories, 0 files
    $ 
    
Re: Directory Structure.
by madtoperl (Hermit) on Mar 31, 2017 at 13:05 UTC
    Hi Nansh
    You can use File::Util for creating sub directories.
    #!/usr/local/bin/perl use strict; use warnings; use File::Util; my($fileHandle) = File::Util->new(); $fileHandle->make_dir('/XXX/YYY/ZZZ/');
Re: Directory Structure.
by pryrt (Abbot) on Mar 31, 2017 at 15:01 UTC

    You've already received good answers. But as an aside, to help clarify your code: hippo's refactoring to foreach my $subdir (@files) implied my suggestion, but I will make it more explicit (and go a little farther): please don't call a list of subdirectories @files, nor an element from that list $file. You'll just confuse anyone else trying to read or sustain your code, and probably yourself in the future, by saying you are changing directory into a file. Use foreach my $subdir ( @subdirs ), or $name ... @names, or $vehicle, or $machine, or $thingamagoob. It's helpful to give the variables names meaningful to the context -- but please, please, whatever you do, don't give it a name that's misleading, confusing, or wrong for the context. Please. :-)

Re: Directory Structure.
by oldtechaa (Beadle) on Mar 31, 2017 at 12:10 UTC
    In the future, please post to Seekers of Perl Wisdom. Perl Monks Discussion is not the right place for posts that have nothing to do with this website and how it works. I see that Eily has already considered this for moving.
Re: Directory Structure.
by duyet (Friar) on Apr 01, 2017 at 09:39 UTC
    There are already good responses with creating the dirs, but on Unix system you can do the following:
    `mkdir -p VEHICLES/{CARS,BIKES}`
    which yields:
    $ tree VEHICLES/ VEHICLES/ |-- BIKES |-- CARS 2 directories, 0 files

      When doing this, keep in mind that using backticks (``) or the qx// quote-like operator, the command provided is passed through the shell (/bin/sh, whatever THAT really is) and subject to all the usual shell magic. This may be a problem if you're not expecting it, and a security issue if you're passing user input to the shell.

      In order to avoid the shell, use system instead and pass a list:

      #!/usr/bin/perl # ... system ("mkdir", "-p", map { "$dir/$_" } @files);
        if you're passing user input to the shell

        if youre passing data from untrusted sources unlaundered into the shell (see perlsec) is both more general and to the point. If I'm the user - whom I mostly trust - there's nothing wrong with my data. Except if there is, of course.

        </nitpick>

        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1186609]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2024-07-21 13:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.