0

I got a file with a path on each line. I insert those lines into an array @dirs. Some of the paths include environment variables. An example of a valid file with paths:

/some/valid/path
$HOME/dir
$SOME_ENV/dir

Each path, I would like to check if it contains a file called abc. So I use:

foreach my $dir (@dirs) {
   chmod($dir);
   my $file = $dir."/"."abc";
   print "invalid dir: $dir" unless((-e $file) && (-s $file));
}

But, for some reason, it does not recognize the environment variables, meaning it fails even though $SOME_ENV/dir contains the abc file.

Also, the script does recognize those environment variables, if I use it as following:

print $ENV{SOME_ENV}."\n";
print $ENV{HOME}."\n";

Furthermore, I tried to use the abs_path of the Cwd module, in order to get the real path of the path (so it won't include the environment variable), but it also, does not recognize the environment variable.

why (-e $file) does not recognize the environment variable? How can I solve this issue?

TTaJTa4
  • 810
  • 1
  • 8
  • 22
  • What is the exact error message? – mob Nov 02 '18 at 15:55
  • And if they aren't known ahead of time: `no strict 'vars';use Env;` – mob Nov 02 '18 at 15:56
  • 1
    What is that call to `chmod` for? The first parameter should be the new permissions – Chris Turner Nov 02 '18 at 15:56
  • Thanks for the comments. I don't know the paths. user gives a file and I extract the paths from it, into an array. And even though this path to a dir contains `abc`, the check `(-e $file)` will return false, because it just (for some reason) copies the string without using the env. – TTaJTa4 Nov 02 '18 at 16:00
  • 1
    Did you mean to use `chomp` ([perldoc](http://perldoc.perl.org/functions/chomp.html)) instead of `chmod`? – interduo Nov 02 '18 at 22:07

1 Answers1

6

There is nothing in your code evaluating $dir for environment variables inside of it, so you'd need to add that. A very simplistic way could be done like this - using a regular expression to find the variables and then replacing them with their values in the %ENV hash.

$dir =~ s/\$([A-Z0-9_]*)/$ENV{$1}/g;
Chris Turner
  • 8,082
  • 1
  • 14
  • 18
  • Thanks for the answer. This regex won't work for `$SOME_ENV` (only for a string with `A-Z` letters). Also, will it work, if the env is located in the middle/end of the string? – TTaJTa4 Nov 02 '18 at 16:30
  • You can simply add _ inside the character class so it becomes `[A-Z_]`. The regex is not anchored so it will work anywhere in the string. – Grinnz Nov 02 '18 at 16:42
  • @Grinnz sure but what if user has numbers or any other symbol which is not in the `[A-Z]` range? – TTaJTa4 Nov 02 '18 at 16:47
  • @TTaJTa4 `[A-Z0-9_]` will cover digits as well. See [perlrecharclass](https://perldoc.pl/perlrecharclass#Bracketed-Character-Classes) for more on how character classes work. – Grinnz Nov 02 '18 at 16:49
  • 1
    Also the /e modifier is not necessary, since `$ENV{$1}` will interpolate fine on its own. – Grinnz Nov 02 '18 at 16:50
  • I think that `$dir =~ s/\$(\S+?)(\/|$)/$ENV{$1}$2/g;` is a better solution. it will handle any symbol until the first `/` or the end of the line. What do you think? – TTaJTa4 Nov 02 '18 at 17:11
  • @TTaJTa4 `s/\$([^\s/]+)/$ENV{$1}/g` is a simpler way to achieve that without backtracking. Read as many non-space non-slash characters as follow the `$`. – Grinnz Nov 02 '18 at 17:49
  • 1
    See related https://stackoverflow.com/questions/2821043/allowed-characters-in-linux-environment-variable-names, if you're curious why [A-Z0-9_] should be sufficient as a character class vs more permissive negated character classes. – Automaton Nov 03 '18 at 00:36