Home > database >  Resolving a symlink without readlink utility
Resolving a symlink without readlink utility

Time:01-06

I am trying to use a perl one liner to print a string using regex match in unix command line pipeline.

ls -l /APPL

gives output

lrwxrwxrwx 1 root system 4 Nov 27 12:07 /APPL -\> /PRD

My goal is to print 'PRD'

the command I am using

ls -l /APPL | perl -ne 'print "$1\\n" if / \/APPL\s\S \s\s\/(\S )\s/'

I was tracking it with regex debugger https://regex101.com/ and it looks like it looses it at \/(\S )\s

I am using AIX on a system without the readlink command-line utility. I know I could use awk, but this is not the case here.

CodePudding user response:

Prints the value of a symlink:

readlink /APPL
perl -le'print readlink( $ARGV[0] )' /APPL

Converts to an absolute path with all symlinks (if any) resolved:

readlink -e /APPL
perl -MCwd=abs_path -le'print abs_path( $ARGV[0] )' /APPL
perl -le'use Cwd qw( abs_path ); print abs_path( $ARGV[0] )' /APPL

CodePudding user response:

Just use the single command line (implies GNU/Linux like OS, *BSD):

echo $(basename $(readlink /APPL))

CodePudding user response:

Your regex doesn't match because you match two consecutive spaces between the greater than sign and the backslash at the start of "PRD". Replace that with a single space at it seems to work.

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

$_ = 'lrwxrwxrwx 1 root system 4 Nov 27 12:07 /APPL -> /PRD';

if (m[/APPL\s\S \s/(\S )]) {
  say $1;
} else {
  warn "No match\n";
}

Note that I've also replaced /.../ with m[...] so that I can use / in my regex without escaping it.

However as others have noted - this is the wrong approach. If you're trying to work out where a symbolic link points to, then you should use the readlink() function.

  • Related