• Uncategorized

About linux : Perl-How-to-get-unresolved-value-of-symlink-in-Bin

Question Detail

I have a script at location: “/home/ppp/testing/dir3/script1.pl”, where testing is a symlink pointing to dir1/dir2 (testing -> dir1/dir2)

i.e. resolved path of script1.pl is “/home/ppp/dir1/dir2/dir3/script1.pl”

Now, in my script1.pl, i have used $Bin where I want $Bin value to be /home/ppp/testing/dir3. But, $Bin is storing the value as /home/ppp/dir1/dir2/dir3 (It is resolving the symlink value).

Snippet of code is :

use FindBin qw($Bin $RealBin);
print "Value of bin is $Bin\n";

Output: Value of bin is /home/ppp/dir1/dir2/dir3
But I want: Value of bin is /home/ppp/testing/dir3

How can I achieve this? In short, I want the unresolved value of symlink in $Bin.

I can’t use Path::Tiny module, as this is not installed in my system, and I am not authorized to install any module.

Question Answer

You can’t, at least not on Linux. The system call to return the current work directory always returns an absolute path with symlinks resolved. So if you want an absolute path, it will necessarily have the symlinks resolved.

$ cd /home/ikegami/tmp   # A symlink to /tmp/ikegami

$ cat a.c
#include <stdio.h>
#include <unistd.h>

int main(void) {
   enum { N = 65536 };
   char cwd[N];
   getcwd(cwd, N);
   printf("%s\n", cwd);
}

$ gcc -Wall -Wextra -pedantic a.c -o a

$ ./a
/tmp/ikegami

$ /home/ikegami/tmp/a
/tmp/ikegami

$ perl -e'chdir "/home/ikegami/tmp"; exec "a"'   # Shows it's not the shell's doing.
/tmp/ikegami

Same goes for /proc/$$/cwd.

$ cd /home/ikegami/tmp   # A symlink to /tmp/ikegami

$ readlink /proc/$$/cwd
/tmp/ikegami

$ perl -M5.014 -e'chdir "/home/ikegami/tmp"; say readlink "/proc/$$/cwd"'
/tmp/ikegami

The only way to avoid resolving symlinks is to use

use File::Basename qw( dirname );

dirname($0)

But that doesn’t provide an absolute path. It’s strictly based on the path provided to exec.

$ cd /home/ikegami/tmp   # A symlink to /tmp/ikegami

$ cat a.pl
#!/usr/bin/perl
use 5.014;
use File::Basename qw( dirname );
say dirname($0);

$ a.pl
.

$ ./a.pl
.

$ ./././a.pl
././.

$ /home/ikegami/tmp/a.pl
/home/ikegami/tmp

$ /tmp/ikegami/a.pl
/tmp/ikegami

In short, you have an XY Problem.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.