Making $exeDir smart about symlinks

Started by todd, January 07, 2019, 04:46:05 PM

Previous topic - Next topic

todd

Wow, what a fabulous script! 

First thing I wanted to do on untarring it (linux) was to put it and its dependencies in /opt/exiftool, then create a symlink in /usr/local/bin that points to the exiftool script.  So... exiftool is smart about finding its dependent ./lib directory if exiftool is on the path, but not if what it finds is a symlink.  To make exiftool smart about whether it is itself a symlink or a real file, I changed this (line 20 of version 11.23):

    # get exe directory
    $exeDir = ($0 =~ /(.*)[\\\/]/) ? $1 : '.';

to this:

    # get exe directory
    use Cwd qw( abs_path );
    my $exeFile = abs_path( __FILE__ );
    $exeDir = ($exeFile =~ /(.*)[\\\/]/) ? $1 : '.';

and now exiftool finds its lib even if it's started through a symlink

Again, thank you for your excellent work!



Phil Harvey

Thanks for the suggestion.  I'll try this out, but the code will be a bit more complex because I want this to fall back to the original behaviour if Cwd isn't available.  (ExifTool doesn't "use" any external modules to make it more independent, and hence more reliable.)

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

todd

Of course!  How about this then:

    # get exe directory
    my $exeFile = (-l $0) ? readlink $0 : $0;
    $exeDir = ($exeFile =~ /(.*)[\\\/]/) ? $1 : '.';

Which is all bog-standard perl, and should work cross-platform though I can't vouch for it on windows.

Phil Harvey

It seems that readlink is not implemented on Win32, but I should be able protect it with an eval to avoid exiftool aborting if I decide to use this.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Phil Harvey

OK.  I think I'll do this:

    $exeDir = ($0 =~ /(.*)[\\\/]/) ? $1 : '.';
    if (-l $0) {
        my $lnk = eval { readlink $0 };
        if (defined $lnk) {
            my $lnkDir = ($lnk =~ /(.*)[\\\/]/) ? $1 : '.';
            $exeDir = (($lnk =~ m(^/)) ? '' : $exeDir . '/') . $lnkDir;
        }
    }


Your code only worked if the symlink was in the current directory or had an absolute path.  If it is another directory with a relative path link then this directory name must be combined with the readlink result.  The above code handles this case.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).