Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
964 views
in Technique[技术] by (71.8m points)

linux - Using Bash environment variables from within a Perl script?

I am trying to run a Bash command from within my Perl program. However Perl seems to be confusing my Bash $PWD environment variable as a Perl variable.

How can I make it just read it all as a string?

This is what I'm trying to run

my $path = /first/path;
`ln -s $path $PWD/second/path`

Those backticks runs the second line in Bash. Using System() produces the same problem.

Any ideas?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are two queries here, on use of Bash variables and on running external commands.

There is the %ENV hash in Perl, with environment variables

perl -wE'say $ENV{PWD}'

However, you are often better off getting the equivalent within the script, as things may have a subtly different meaning for the script or change as the script runs.

More importantly, using shell commands exposes you to all kinds of potential problems with quoting, shell injection, and interpretation. For instance, the command you show is dangerous, as outlined in Charles Duffy comment. It is in principle better to use Perl's rich functionality. See for example

for a sober, and detailed, account of advantages.


In case you do need to run external commands, it is best to avoid the shell altogether, for example by using the multi-argument form of system. If you need the output of the command as well there are various modules in Perl that provide that. See links below.

If you also need to use the shell's capabilities, instead of quoting everything just right in order for the shell to receive what it needs better use a ready tool like String::ShellQuote.

Some examples:

Note that qx operator (backticks) uses /bin/sh, which may or may not get relegated to Bash. So if you want Bash you'll need system('/bin/bash', '-c', @cmd). See the links with examples.


Here is a full example related to the objective behind the question.

Your program's working directory may be other than expected depending on how it's started. For one, it changes after chdir. I don't know your exact intent with PWD, but in Perl there are core Cwd::cwd and FindBin with $RealBin, for the current working directory and for the directory where the script resides (generally different things).

To create a symbolic link to $path, with the relative path following the current working directory

use warnings;
use strict;
use Cwd qw(cwd);

my $cwd = cwd;

my $path = '/first/path';

symlink($path, "$cwd/second/path") or die "Can't make a symlink: $!";

If the path is meant to be the script's location use $RealBin from FindBin instead of cwd.

Note that with symlink you cannot pass a directory instead of a link name. See this page.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...