What does the following do exactly?
newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
if expr "x${newProg}" : 'x/' >/dev/null; then
prog="${newProg}"
else
progdir=`dirname "${prog}"`
prog="${progdir}/${newProg}"
fi
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityWhat does the following do exactly?
newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
if expr "x${newProg}" : 'x/' >/dev/null; then
prog="${newProg}"
else
progdir=`dirname "${prog}"`
prog="${progdir}/${newProg}"
fi
The first line uses expr
to:
$newProg
against the basic regular expression .* -> \(.*\)$
(anchored on both ends). That's anything with ->
in it.newProg
to the part of the original value matched by the capturing subexpression written in parentheses (the part after ->
).The greedy matching semantics are such that this always captures and outputs the last such match, so there is never a ->
in the output.
This would, for example, parse the output of ls -l
on a symlink to find the target (given well-behaved filenames, etc, usual caveats).
The second line uses expr
again to check whether the new value of newProg
begins with a /
, i.e., it represents an absolute path.
In the case where it does, prog
is just set to that value. Otherwise, prog
is set to a computed relative path using dirname
on $prog
, a variable not defined in this snippet. The effect will presumably be to construct a path relative to that original location.
If you are only targeting a more capable shell or environment than pure POSIX, there is likely to be a more reliable way of doing this than expr
. readlink
is a very commonly-available command also, which would save on parsing ls
.
ls
is always a bad idea, and using expr
to parse ls is also inefficient and leads to ugly, difficult to read shell code....especially when every version of test
aka [
in existence has -h
and/or -L
options to test whether a file is a symlink or not.
– cas
Jul 16 '17 at 4:14
[ -L "$newProg" ] && prog="$(readlink -m "$newprog")"
(1 line rather than 7). And if $progdir is required (i.e. not just a temporary throwaway variable), append && progdir="$(dirname "$prog")"
to that line. BTW, the [ -L ... ] &&
test isn't required because running readlink -m
on a non-symlink filename just returns that filename (with the full path).
– cas
Jul 16 '17 at 4:17