Getting Absolute Paths of UNIX Directories and Filenames in Shell Scripts
This post is a compilation of the function getabspath() for different shells that can be used to get the absolute form of a path. The function accepts an argument path then returns the absolute form of it to the variable $__.
bash (3.0 and newer only)
bash (2.05b and newer only)
bash (all stable versions)
ksh (original)
pdksh
zsh
any other shell based from the original sh
getabspath.c - see http://www.linuxquestions.org/questi...ml#post3648275
bash (3.0 and newer only)
Code:
function getabspath {
local -a T1 T2
local -i I=0
local IFS=/ A
case "$1" in
/*)
read -r -a T1 <<< "$1"
;;
*)
read -r -a T1 <<< "/$PWD/$1"
;;
esac
T2=()
for A in "${T1[@]}"; do
case "$A" in
..)
[[ I -ne 0 ]] && unset T2\[--I\]
continue
;;
.|'')
continue
;;
esac
T2[I++]=$A
done
case "$1" in
*/)
[[ I -ne 0 ]] && __="/${T2[*]}/" || __=/
;;
*)
[[ I -ne 0 ]] && __="/${T2[*]}" || __=/.
;;
esac
}
Code:
function getabspath {
local -a T=()
local -i I=0
local IFS=/ A
case "$1" in
/*)
__=$1
;;
*)
__=/$PWD/$1
;;
esac
while read -r -d / A; do
case "$A" in
..)
[[ I -ne 0 ]] && unset T\[--I\]
continue
;;
.|'')
continue
;;
esac
T[I++]=$A
done <<< "$__/"
case "$1" in
*/)
[[ I -ne 0 ]] && __="/${T[*]}/" || __=/
;;
*)
[[ I -ne 0 ]] && __="/${T[*]}" || __=/.
;;
esac
}
Code:
function getabspath {
local -a T=()
local -i I=0
local IFS=/ A
case "$1" in
/*)
__=$1
;;
*)
__=/$PWD/$1
;;
esac
while read -r -d / A; do
case "$A" in
..)
[[ I -ne 0 ]] && unset T\[--I\]
continue
;;
.|'')
continue
;;
esac
T[I++]=$A
done << .
$__/
.
case "$1" in
*/)
[[ I -ne 0 ]] && __="/${T[*]}/" || __=/
;;
*)
[[ I -ne 0 ]] && __="/${T[*]}" || __=/.
;;
esac
}
Code:
if
__=.
read __ <<< "$__"
[[ $__ = '"."' ]]
then
function getabspath {
typeset T1 T2
typeset -i I=0
typeset IFS=/ A
case "$1" in
/*)
read -r -A T1 <<< $1
;;
*)
read -r -A T1 <<< $PWD/$1
;;
esac
set -A T2
for A in "${T1[@]}"; do
case "$A" in
..)
[[ I -ne 0 ]] && unset T2\[--I\]
continue
;;
.|'')
continue
;;
esac
T2[I++]=$A
done
case "$1" in
*/)
[[ I -ne 0 ]] && __="/${T2[*]}/" || __=/
;;
*)
[[ I -ne 0 ]] && __="/${T2[*]}" || __=/.
;;
esac
}
else
function getabspath {
typeset T1 T2
typeset -i I=0
typeset IFS=/ A
case "$1" in
/*)
read -r -A T1 <<< "$1"
;;
*)
read -r -A T1 <<< "$PWD/$1"
;;
esac
set -A T2
for A in "${T1[@]}"; do
case "$A" in
..)
[[ I -ne 0 ]] && unset T2\[--I\]
continue
;;
.|'')
continue
;;
esac
T2[I++]=$A
done
case "$1" in
*/)
[[ I -ne 0 ]] && __="/${T2[*]}/" || __=/
;;
*)
[[ I -ne 0 ]] && __="/${T2[*]}" || __=/.
;;
esac
}
fi
Code:
getabspath() {
typeset A T IFS=/ TOKENS I=0 J=0
A=${1%/}
if [[ -n $A ]]; then
while :; do
T=${A%%/*}
case "$T" in
..)
if [[ I -gt 0 ]]; then
unset TOKENS\[--I\]
else
(( ++J ))
fi
;;
.|'')
;;
*)
TOKENS[I++]=$T
;;
esac
case "$A" in
*/*)
A=${A#*/}
;;
*)
break
;;
esac
done
fi
__="/${TOKENS[*]}"
if [[ $1 != /* ]]; then
A=${PWD%/}
while [[ J -gt 0 && -n $A ]]; do
A=${A%/*}
(( --J ))
done
[[ -n $A ]] && __=$A${__%/}
fi
if [[ $__ = / ]]; then
[[ $1 != */ ]] && __=/.
elif [[ $1 == */ ]]; then
__=$__/
fi
}
Code:
function getabspath {
local -a TOKENS; set -A TOKENS
local -i I=0
local IFS=/ T
__=$1
case "$1" in
/*)
set -- ${=1}
;;
*)
set -- ${=PWD} ${=1}
;;
esac
for T; do
case "$T" in
..)
[[ I -ne 0 ]] && TOKENS[I--]=()
continue
;;
.|'')
continue
;;
esac
TOKENS[++I]=$T
done
case "$__" in
*/)
[[ I -ne 0 ]] && __="/${TOKENS[*]}/" || __=/
;;
*)
[[ I -ne 0 ]] && __="/${TOKENS[*]}" || __=/.
;;
esac
}
Code:
# first version - assuming the script doesn't mind 'set -f' being set
getabspath() {
case "$1" in
/*)
__=$1
;;
*)
__=`exec pwd`/$1
;;
esac
set -f
IFS=/
set -- $__
while :; do
__='' __L=''
for __A; do
shift
case "$__A" in
..)
[ -z "$__L" ] && continue
shift "$#"
set -- $__ "$@"
continue 2
;;
.|'')
continue
;;
esac
[ -n "$__L" ] && __=$__/$__L
__L=$__A
done
__=$__/$__L
break
done
unset __A __L
case "$1" in
*/)
[ ! "$__" = / ] && __=$__/
;;
*)
[ "$__" = / ] && __=/.
;;
esac
}
# 2nd version - encapsulates settings inside a subshell
getabspath() {
case "$1" in
/*)
__=$1
;;
*)
__=`exec pwd`/$1
;;
esac
__=`
set -f
IFS=/
set -- $__
while :; do
__='' L=''
for A; do
shift
case "$A" in
..)
[ -z "$L" ] && continue
shift "$#"
set -- $__ "$@"
continue 2
;;
.|'')
continue
;;
esac
[ -n "$L" ] && __=$__/$L
L=$A
done
__=$__/$L
break
done
echo "$__"
`
case "$1" in
*/)
[ ! "$__" = / ] && __=$__/
;;
*)
[ "$__" = / ] && __=/.
;;
esac
}
# 3rd version - try to make things run faster; prevent it from reparsing commands
getabspath() {
case "$1" in
/*)
__=$1
;;
*)
__=`exec pwd`/$1
;;
esac
__=`getabspath_`
case "$1" in
*/)
[ ! "$__" = / ] && __=$__/
;;
*)
[ "$__" = / ] && __=/.
;;
esac
}
getabspath_() {
set -f
IFS=/
set -- $__
while :; do
__='' L=''
for A; do
shift
case "$A" in
..)
[ -z "$L" ] && continue
shift "$#"
set -- $__ "$@"
continue 2
;;
.|'')
continue
;;
esac
[ -n "$L" ] && __=$__/$L
L=$A
done
__=$__/$L
break
done
echo "$__"
}
# 4th version - just using awk (some shells doesn't work with the ones above)
getabspath() {
__=`
awk -- '
BEGIN {
PATH = ARGV[1]
if (ARGV[1] !~ "^[/]")
PATH = ARGV[2] "/" PATH
FS = "/"
$0 = PATH
T = 0
for (F = 1; F <= NF; F++) {
if ($F == "." || $F == "") {
continue
} else if ($F == "..") {
if (T)
--T
} else {
TOKENS[T++]=$F
}
}
if (T) {
for (I = 0; I < T; I++)
ABS = ABS "/" TOKENS[I]
if (PATH ~ /\/$/)
ABS = ABS "/"
} else if (PATH ~ /\/$/) {
ABS = "/"
} else {
ABS = "/."
}
print ABS
exit
}
' "$1" "`exec pwd`"
`
}
Total Comments 0




