[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: equivalent of Linux readlink -f in pure bash?
From: |
Bernd Eggink |
Subject: |
Re: equivalent of Linux readlink -f in pure bash? |
Date: |
Wed, 10 Aug 2011 12:00:22 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux i686; rv:5.0) Gecko/20110714 Thunderbird/5.0 |
On 09.08.2011 15:50, Steven W. Orr wrote:
On 8/9/2011 5:29 AM, Bernd Eggink wrote:
On 09.08.2011 03:44, Jon Seymour wrote:
Has anyone ever come across an equivalent to Linux's readlink -f
that is implemented purely in bash?
You can find my version here:
http://sudrala.de/en_d/shell-getlink.html
As it contains some corrections from Greg Wooledge, it should
handle even pathological situations. ;)
Bernd
I'd just like to make a couple of suggestions for your script (I hope
these are welcome):
You are welcome!
*) You reset OPTIND to 1 but you didn't declare it local. This will
cause any caller of getlink which uses getopts to reset its variable
to 1. (I mention this because it cost me a couple of hours a while
back.)
The reason I didn't declare OPTIND local is that OPTIND is handled
specially by the shell; there is always exactly _one_ instance of this
variable. In other words, OPTIND is always global, even if declared
local (which is indeed pretty weird). Try this:
-------------------------------
function f
{
local OPTIND=1
echo "\$1=$1"
}
while getopts "abcdefg" opt
do
echo "opt=$opt"
f $opt
done
--------------------------------
Calling the sript like this works fine:
script -a -b -c
But calling it like this leads to an endless loop:
script -abc
One could of course save and restore the original:
-------------------------------
function f
{
local oldind=$OPTIND
OPTIND=1
echo "\$1=$1"
OPTIND=$oldind
}
-------------------------------
However, this also loops endlessly. The reason is most likely that bash
maintains an additional internal variable holding the index of the
current character, relative to the current word. While this variable is
not directly accessible by the user, it is set to 0 whenever OPTIND is
assigned a value.
So the only safe way is to _never_ use getopts within another getopts
block, but always wait until the first one has finished.
When calling getopts, especially from a function that is intended to
not be used at a top level for processing command line options, you
should declare local copies of OPTIND, OPTARG and OPTERR.
*) To remove the trailing slashes, instead of
while [[ $file == */ ]] do file=${file%/} done
file=${file##*/} # file name
just say file="${file%${file##*[!/]}}"
Yes, you can do that, but I find my version a bit more legible. Also,
for file=/ it returns a single slash, while yours returns an empty
string. (Hmm... the next statement in my script also creates an empty
string, but this is a bug and will be fixed).
*) Instead of
[[ ! -d $dir ]] && { ret=1 break }
how about this for slightly cleaner?
[[ -d $dir ]] || { ret=1 break }
I think that's just a matter of taste.
Greetings,
Bernd
--
http://sudrala.de
- Re: equivalent of Linux readlink -f in pure bash?, (continued)
- Re: equivalent of Linux readlink -f in pure bash?, Bob Proulx, 2011/08/08
- Re: equivalent of Linux readlink -f in pure bash?, Jon Seymour, 2011/08/09
- Re: equivalent of Linux readlink -f in pure bash?, Bob Proulx, 2011/08/09
- Re: equivalent of Linux readlink -f in pure bash?, Jon Seymour, 2011/08/09
- Re: equivalent of Linux readlink -f in pure bash?, Jon Seymour, 2011/08/09
- Re: equivalent of Linux readlink -f in pure bash?, Bob Proulx, 2011/08/09
- Re: equivalent of Linux readlink -f in pure bash?, Jon Seymour, 2011/08/09
- Re: equivalent of Linux readlink -f in pure bash?, Andreas Schwab, 2011/08/09
Re: equivalent of Linux readlink -f in pure bash?, Bernd Eggink, 2011/08/09
Re: equivalent of Linux readlink -f in pure bash?, Jon Seymour, 2011/08/09
Message not available
Message not available
Re: equivalent of Linux readlink -f in pure bash?, Stephane CHAZELAS, 2011/08/11