Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

perl chdir not working, not changing the directory

Tags:

perl

My complete perl script is

chdir ("/etc" or die "cannot change: $!\n");
print  "\nCurrent Directory is $ENV{PWD} \n";

and I am getting output (not as expected)

bash-3.2$ perl test.pl 

Current Directory is /home

P.S. /home is where I am executing the test.pl

like image 808
Arjun Bora Avatar asked Sep 04 '13 07:09

Arjun Bora


People also ask

How do I change directory in Perl?

You can use chdir function in Perl to change a directory and go to a new location. You will need to have the required permission to change a directory and go inside the new directory.

How do I change directory in Perl Windows?

Use chdir. If both a drive and a directory is provided, both the current drive and the current directory on that drive will be changed. This differs from the cd shell command which only does the latter. Both slashes (\ and /) can be used as a separator and to prefix a UNC path.

How do I get the current directory in Perl?

getcwd and friends my $cwd = getcwd(); Returns the current working directory.

How do you create directory in Perl If not exist?

The make_path function creates the given directories if they don't exist before, much like the Unix command mkdir -p . The function accepts a list of directories to be created.


2 Answers

  1. You should move or die outside of chdir(...), i.e.:

    chdir("/etc") or die "cannot change: $!\n";
    

    With what you have currently, the expression "/etc" or die "cannot change: $!\n" is evaluated first. Its result is "/etc" and die() never gets executed. or die() should be "applied to" chdir() call, not to its argument.

  2. Do print(cwd); to print current working directory. Don't forget to use Cwd;


use Cwd;

chdir("/etc") or die "cannot change: $!\n";
print(cwd);
like image 111
Alex Shesterov Avatar answered Oct 29 '22 15:10

Alex Shesterov


Alex Shesterov has given the right answer, but since this has some interesting details, I will elaborate. Here is the documentation for or:

Binary "or" returns the logical disjunction of the two surrounding expressions. It's equivalent to || except for the very low precedence. This makes it useful for control flow:

print FH $data    or die "Can't write to FH: $!";

This means that it short-circuits: the right expression is evaluated only if the left expression is false.

What the Perl documentation writer meant by "This means that", I guess we'll never know, but the following part of the sentence is important: It short-circuits.

In Perl, "true" and "false" are handled somewhat conveniently, in that there are only a few false values, and all other values are considered true. For example, undef, 0, the empty string and the empty list are examples of "false" values. And a string such as the one in this question "/etc" can never be false.

When passing arguments to a function/subroutine, lists are used. A list is a series of independent statements, such as:

"foo", "bar", "baz"  # three strings, foo bar baz
qw(foo bar baz)      # same thing
my @array = qw(foo bar baz);
@array;              # same thing, unless scalar context

However, the or operator does not create a list, rather it forces the statement to be evaluated right away, before it is passed to the function. So, this is what happens:

chdir ("/etc" or die "cannot change: $!\n");
#      ^^^^^^-- true value
--> "/etc" or die ? --> "/etc"
chdir("/etc");

You have found a new version of this classic mistake. Usually this is what people do:

open my $fh, "<", "file" || die "Cannot open: $!";

Which is the same mistake, in a more subtle version: The logical or || operator has higher precedence than the comma operator, which makes the above statement similar to:

open my $fh, "<", ( "file" || die "Cannot open: $!" );

Which is exactly the problem you ran into: The die statement can never logically be executed, since a string with a file name can never (unless it is empty, or zero) be false.

like image 31
TLP Avatar answered Oct 29 '22 13:10

TLP