http://www.perlmonks.org?node_id=11110217

Skeeve has asked for the wisdom of the Perl Monks concerning the following question:

I'm wondering how I could create a relative symlink in perl.

Currently I'm using symlink in a perl script running in a docker container. The created link is an absolute link - for the container. On the docker host otoh this link is a broken link.

Now I'm wondering whether or not it's possible to create relative links in perl. I fear this can only be done by changing to the directory where the original file resides or by relying on a systemcall invoking ln -rs …, right?

But maybe someone here has another good idea?


s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
+.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e

Replies are listed 'Best First'.
Re: create a relative symlink
by dave_the_m (Monsignor) on Dec 16, 2019 at 08:15 UTC
    It's not clear to me what your issue is. If the target of the symlink is specified as a relative path, then then the symlink will be relative. Can you give a concrete example of your issue?

    Dave.

      Thanks for asking, Dave.

      The issue here is, that my script is not running in the directory where the target is. Currently the linking looks something like this

      my $newname="/home/script/data/archive/currentfile";
      my $targetfile="/home/script/data/archive/infofile-2019-12-16";
      symlink $targetfile, $newname;
      

      In order for the link to become relative I think I will have to do a chdir to the directory of $newname and make the path of $targetfile be relative to that.

      As both are in my case, in the same directory, the relative-path part is easy, but would it be different directories, it would be a bit more complicated.

      As the script is not running in the /home/script/data/archive directory, I think for symlink to create a working relative link, I need to do a chdir first. But then I need to change directory back as well.

      As the ln command has a "make a relative link" option, I thought there might be something available in perl as well. So in order not to reinvent the wheel, I'm asking…


      s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
      +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
        my $newname="/home/script/data/archive/currentfile"; my $targetfile="infofile-2019-12-16"; symlink $targetfile, $newname;
        to create a working relative link, I need to do a chdir first
        That would be the easiest way. However, it seems that you simply need to calculate the relative link (relative to the folder/directory where the symlink-to-be shall reside), e.g. with Path::Tiny->relative()
        my $newname="/home/script/data/archive/currentfile"; my $targetfile="/home/script/data/archive/infofile-2019-12-16"; # untested use Path::Tiny 'path'; my $newdir = path($newfile)->parent(); my $linktarget = path($targetfile)->relative($newdir); print ":$linktarget:\n"; symlink $linktarget, $newname;
Re: create a relative symlink
by Anonymous Monk on Dec 18, 2019 at 03:24 UTC
    Does any operating system actually support a relative symlink?
      Yes. In linux, you can easily create one:
      ln -s .. parent

      If you then move the link somewhere else, e.g. with

      mv parent ..

      it will now point to its new parent directory.

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
        Yes. In linux,

        Make that any POSIX-compatible system. A limit is the filesystem: The respective native filesystems generally support symlinks, but e.g. FAT does not.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)