On Thu, Jul 13, 2006 at 11:53:00PM -0600, Bob Proulx wrote: > Stephane Chazelas wrote: > > $0 will always contain the file path, unless the script was > > started as: > > > > bash script.sh > > > > And there's no script.sh in the current directory (in which case > > sh/bash will have looked up script.sh in $PATH). > > Of course using command as you have done will work for bash.
"command" is a POSIX command. So will work with every POSIX and therefore every Unix conformant sh. Note that on some systems, the Unix conformant sh is not in /bin, you may need to adapt the she-bang line (note that the she-bang line is a non-standard Unix feature). > But I > always feel better about using portable shell as much as possible. > here is one way. > > pathfind() { > OLDIFS="$IFS" > IFS=: > for p in $PATH; do > if [ -x "$p/$*" ]; then > IFS="$OLDIFS" > echo "$p/$*" > fi > done > IFS="$OLDIFS" > } On the contrary the code above has many problems: 1- If IFS was unset before, it becomes set to the empty string after which has a different meaning. 2- word splitting when IFS contains non-blank characters varies from one shell to the next, and in most implementations (including bash and AT&T ksh, it differs from the way the shell splits $PATH internally to look up a command ("/bin:" is "/bin" and "" as far as PATH look up is concerned while bash world splitting splits "/bin:" into only "/bin"). 3- you forgot to disable filename generation, which means wildcards will be expanded in "for p in $PATH" 4- there's a "break" (or return 0) missing, a "return 1" missing if there's no match. 5- echo is not a portable command, use printf instead as POSIX suggests. > > > #! /bin/sh - > > dir=$( > > cmd=$0 > > [ -e "$cmd" ] || cmd=$(command -v -- "$cmd") || exit > > dir=$(dirname -- "$cmd") > > cd -P -- "$dir" && pwd -P > > ) || exit > > # untested > > > > should give you the absolute path of the directory portion of > > the script path (unless that directory ends in newline > > characters). > > One thing to note about this script is that it canonicalizes path with > respect to symlinks. You do say that but without much > fanfare. That was intended. You can probably find as many caveats with one approach or the other. Note that if the binary file is a symlink itself, it doesn't canonalise it. [...] > I think it is best to accept whatever path the user has provided > verbatim. I would not try to canonicalize the path in any way. If > the user has provided a path with /foo/bar/../../zoo/zam for example > then I would just go with it because that path may actually be > necessary just like that for some reason as yet unknown at this moment > to us writing the code to be used in the future. The reason I think > this way is that I have tried to do things like canonicalizing > previously myself and gotten burned by it. I have learned it is > better to avoid doing such things. Then: dir=$( cmd=$0 [ -e "$cmd" ] || cmd=$(command -v -- "$cmd") || exit dir=$(dirname -- "$cmd") case $dir in /*) ;; *) dir=$(pwd -P)/$dir || exit;; esac printf '%s\n' "$dir" ) || exit -- Stephane _______________________________________________ Bug-bash mailing list Bug-bash@gnu.org http://lists.gnu.org/mailman/listinfo/bug-bash