Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re: Detecting if a folder is a symbolic link

by Tanktalus (Canon)
on Mar 17, 2006 at 23:04 UTC ( #537607=note: print w/replies, xml ) Need Help??


in reply to Detecting if a folder is a symbolic link

friedo points out -l. I'll add two more pieces: using lstat (which is what -l uses i under the covers), which gets way too complicated, and using readlink to read the symlink.

Note that while you can use the "_" special variable for the -X operators, you need to be careful when you're involving the -l. You can't do if (-d $file && -l _). That will always return false. You must reverse that: if (-l $file && -d _). The reason is that the -d check (and everything except -l) will use stat which follows symlinks reading the underlying file, directory, device, FIFO, whatever. That will never be a symlink (unless it points to a nonexistant entity). Of course, if it points to a nonexistant entity, it won't be a directory ;->

if (-d $file && -l $file) should work fine, albeit the tiniest bit more expensive than if (-l $file && -d _).

Also be careful with readlink. It can be awfully tricky to follow symlinks the way that the OS does. Symlinks to symlinks to files inside symlink'd directories ... it's really convoluted. You're probably better off using stat (not lstat) and using the first two fields (dev and ino) as hash keys to keep track of whether you've seen it or not. This will actually also catch hardlinked files which you probably aren't even thinking about ;-)

{ my %seen; sub have_seen_file { my $file = shift; my ($dev, $ino) = stat($file); $seen{$dev}{$ino}++; } sub reset_seen_files { %seen = () } }
Or something like that.

Update: tye is right - I normally actually use this shortcut as "if (-l $file || -d _)" which, of course, is not what the OP wanted.

Replies are listed 'Best First'.
Re^2: Detecting if a folder is a symbolic link (tricky)
by tye (Sage) on Mar 17, 2006 at 23:46 UTC
    You can't do if (-d $file && -l _). That will always return false.

    True.

    You must reverse that: if (-l $file && -d _).

    Actually, that also always returns a false value. The cached lstat results did not follow the symbolic link and so doesn't know anything about what (if anything) it links to. If you want to check for "X is a (symbolic) link to a directory", then you can't avoid doing [l]stat twice (well, lstat once and stat once).

    There certainly are cases where you can "cheat" (or "be efficient"). Perhaps you were thinking of a very common case, for example:

    if( ! -l $file && -d _ ) { } #or if( -l $file ) { ... } elsif( -d _ ) { ... } elsif( -f _ ) { ... } else { ... }

    That does work and does require that you do the -l part first.

    - tye        

Re^2: Detecting if a folder is a symbolic link
by Anonymous Monk on Dec 03, 2021 at 07:01 UTC
    What does "_" mean here? ( Referring to -d _ )

      It refers to the previous call to stat or other file test. Using the underscore saves a useless second call.

      If stat is passed the special filehandle consisting of an underline, no stat is done, but the current contents of the stat structure from the last stat, lstat, or filetest are returned.

      🦛

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2022-08-11 06:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?