dimanche 6 mai 2018

Why does Perl file test operator "-l" not detect symlinks?

Why does the Perl file test operator "-l" fail to detect symlinks under the following conditions?

System Info

john@testbed-LT:/temp2/test$ uname -a
Linux Apophis-LT 4.13.0-37-generic #42-Ubuntu SMP Wed Mar 7 14:13:23 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

john@testbed-LT:/temp2/test$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 17.10
Release:        17.10
Codename:       artful

Perl Info

john@testbed-LT:/temp2/test$ perl -v

This is perl 5, version 26, subversion 0 (v5.26.0) built for x86_64-linux-gnu-thread-multi (with 56 registered patches, see perl -V for more detail)

Test Resources

john@testbed-LT:/temp2/test$ touch regular_file
john@testbed-LT:/temp2/test$ mkdir dir
john@testbed-LT:/temp2/test$ ln -s regular_file symlink

john@testbed-LT:/temp2/test$ ls -al
total 12
drwxrwxr-x 3 john john 4096 May  6 02:29 .
drwxrwxrwx 6 john john 4096 May  6 02:29 ..
drwxrwxr-x 2 john john 4096 May  6 02:29 dir
-rw-rw-r-- 1 john john    0 May  6 02:29 regular_file
lrwxrwxrwx 1 john john   12 May  6 02:29 symlink -> regular_file

Script Containing Failing "-l" Operator

john@testbed-LT:/temp2/test$ cat ~/.scripts/test.pl
#!/usr/bin/perl

use strict;
use warnings;
use Cwd 'abs_path';

my $targetDir = "/temp2/test";
opendir(DIR, $targetDir) || die "Can't open $targetDir: $!";

while (readdir DIR) {
    my $file = "$_";

    if($file =~ m/^\.{1,2}/) {
        next;
    }

    $file = abs_path($file);

    if(-l "$file") {
        print "Link: $file\n";
    }
    elsif(-d "$file") {
        print "Dir: $file\n";
    }
    elsif(-f "$file") {
        print "File: $file\n";
    }
    else {
        print "\n\n *** Unhandled file type for file [$file]!\n\n";
        exit 1;
    }
}

closedir(DIR);

Script Output

john@testbed-LT:/temp2/test$ perl ~/.scripts/test.pl
File: /temp2/test/regular_file
Dir: /temp2/test/dir
File: /temp2/test/regular_file

Problem I'm Trying to Solve

Note in the above output that the symlink (named "symlink") is not listed while the file, "regular_file," is listed twice (I want "symlink" listed -- the actual link and not the file it points to).

When I change ... if(-l "$file") ... to ... if(lstat "$file") ... in the script, again "symlink" is not listed while "regular_file" is listed twice, but they are being listed from within the block meant to catch symlinks, i.e.:

john@testbed-LT:/temp2/test$ perl ~/.scripts/test.pl
Link: /temp2/test/regular_file
Link: /temp2/test/dir
Link: /temp2/test/regular_file

Goal

The output I'm trying to achieve (which is faked below -- not actually generated by the script, but by hand) is:

john@testbed-LT:/temp2/test$ perl ~/.scripts/test.pl
File: /temp2/test/regular_file
Dir: /temp2/test/dir
Link: /temp2/test/symlink

...but not necessarily in that order (I don't care about the order of the listing).

Why is the above-shown script not achieving the above-stated goal (why is the "-l" operator not working)?

Aucun commentaire:

Enregistrer un commentaire