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
1 Answer 1
The first line uses expr
to:
- Match the value of
$newProg
against the basic regular expression.* -> \(.*\)$
(anchored on both ends). That's anything with->
in it. - Set
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
.
-
+1. the only thing i'd add to that is that parsing the output of
ls
is always a bad idea, and usingexpr
to parse ls is also inefficient and leads to ugly, difficult to read shell code....especially when every version oftest
aka[
in existence has-h
and/or-L
options to test whether a file is a symlink or not.cas– cas2017年07月16日 04:14:58 +00:00Commented Jul 16, 2017 at 4:14 -
A GNU readlink-based alternative to this could look like
[ -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 runningreadlink -m
on a non-symlink filename just returns that filename (with the full path).cas– cas2017年07月16日 04:17:02 +00:00Commented Jul 16, 2017 at 4:17