Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Help with exercise

by codeKnight (Initiate)
on Sep 22, 2017 at 23:46 UTC ( [id://1199939]=perlquestion: print w/replies, xml ) Need Help??

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

Hi guys, I am teaching myself perl and I'm working on an exercise that I'm particularly stumped on. The task is to write a perl script that accepts a valid directory as an argument. Using the argument passed, change into the given directory. Once inside, create two more directories. I've written this exact same script using BASH before and it worked perfectly. I'm just trying to figure out where I'm going wrong because as of right now, the script does nothing. Here's what I have:
#!/usr/bin/perl #Script to create required directories in user provided location argum +ent. my $Dir = $ARGV[0]; if(! -e "$Dir") { print "Please try again with a valid directory.\n"; exit 1; } elsif(! -d "$Dir") { print "Please try again with a valid directory.\n"; exit 1; } elsif(($#ARGV+1) < 1) { print "Please try again with a valid directory.\n"; exit 1; } #Change to user selected location chdir($Dir);

Replies are listed 'Best First'.
Re: Help with exercise
by Laurent_R (Canon) on Sep 23, 2017 at 09:02 UTC
    Hi codeKnight,

    In addition to what Anonymous Monk said, I would comment that this conditional statement:

    elsif(($#ARGV+1) < 1) {
    is a bit strange. First, it would be simpler to test:
    elsif ($#ARGV < 0) {
    (Note that if no argument is passed, $#ARGV will be -1.)

    Second, if you want to test the number of arguments passed to the program, it is clearer to evaluate @ARGV in scalar context (which gives the number of items in that array):

    elsif (@ARGV < 1) { # or, if you prefer an explicitly stated scalar context: elsif (scalar @ARGV < 1) {
    Last, but not least, this conditional statement will never be true because, if you don't pass any argument, this statement will not be executed: the program will die with the first conditional
    if(! -e "$Dir") {
    In fact, it is quite strange to check if an argument is passed after having checked whether the value of the argument is a valid directory.

    So if you want to check that at least one argument is being passed to the program, you should do it first.

    Also, it is a bit useless to check for the existence of $Dir and then whether it is a valid directory (unless you want to print a different message in that case); you can check directly that it is a valid directory.

    So, this program could be rewritten as:

    use strict; use warnings; die "Please supply an argument to the program" if @ARGV < 1; my $dir = shift; die "Please try again with a valid directory.\n" unless -d $dir; # Change to user selected location chdir $dir; mkdir "FirstSubDir"; mkdir "SecondSubDir";
      In keeping with your recommended best practices of error checking at each step, the main code should be
      chdir $dir or die "ERROR: Could not change directory to $dir +"; mkdir "FirstSubDir" or die "ERROR creating FirstSubdir:$!"; mkdir "SecondSubDir" or die "ERROR creating SecondSubDir:$!";

                      All power corrupts, but we need electricity.

        of course once we get into checking the returns, we may find chdir does all the testing we need already ...

        use strict; use warnings; use Cwd; my $dir = shift; chdir $dir or die "Couldn't chdir $dir: $!\n"; print "OK, in ". getcwd . "\n";

        And the outut

        # ./change.pl Downloads/ OK, in /home/Random/Downloads # ./perl change.pl foo Couldn't chdir foo: No such file or directory # ./mkdir bar # ./chmod 000 bar # ./perl change.pl bar Couldn't chdir bar: Permission denied

        Cheers,
        R.

        Pereant, qui ante nos nostra dixerunt!
        Yes, agreed ++. Here, I wanted to keep it simple in the context of an exercise.

        Although, to tell the full truth, I am not sure I would really check the chdir return status after I have checked that $dir contains a valid directory entry in the current directory (I know it might still fail for various reasons, such as missing privileges, but this is quite unlikely in my context and, sometimes, there is a trade-off between code complexity and coding efficiency). Or I might probably use the autodie module in such a context with a lot of system calls.

        Update: or, as suggested by Random_Walk, we might go the other way around and let chdir do the checks.

Re: Help with exercise
by Anonymous Monk on Sep 23, 2017 at 04:21 UTC

    Hi,

    You've forgotten to mkdir the directories.

    Also, always, always, always use strict and warnings, always, get in the habit now, it will save you much time and trouble in the future.

    Also, always etc. check return values, it will save etc.

    J.C.

Re: Help with exercise
by Anonymous Monk on Sep 23, 2017 at 00:02 UTC
    You didn't... actually... create the directories. Use mkdir. Also, it's not necessary to test -d and -e separately, because the former implies the latter.
      I know I didn't create any. Right now, my script won't change into the directory given as an argument. For example, inside my ubuntu terminal I created a directory called test. then I tried to run the script with "test" as an argument. I expected to then be inside of test. Nothing happened.

        Any changes to what is the current directory made while running perl disapear when perl ends.

        in your perl script add

        use Cwd; print 'Cwd:'.getcwd."\n";
        after the
        chdir($Dir);
        and you will see that you did move to that directory while perl was running.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (1)
As of 2024-04-25 01:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found