если Вы желаете громко жевать часть имени файла от пути, "dirname" и "базовое имя" являются Вашими друзьями, и "realpath" удобен также.
dirname /foo/bar/baz
# /foo/bar
basename /foo/bar/baz
# baz
dirname $( dirname /foo/bar/baz )
# /foo
realpath ../foo
# ../foo: No such file or directory
realpath /tmp/../tmp/../tmp
# /tmp
realpath
альтернативы
, Если realpath
не поддерживается Вашей оболочкой, можно попробовать
readlink -f /path/here/..
Также
readlink -m /path/there/../../
Работы то же как [1 111]
realpath -s /path/here/../../
, в котором путь не должен существовать, чтобы быть нормализованным.
Попробуйте realpath
. Ниже источник в целом, настоящим пожертвованный общественному достоянию.
// realpath.c: display the absolute path to a file or directory.
// Adam Liss, August, 2007
// This program is provided "as-is" to the public domain, without express or
// implied warranty, for any non-profit use, provided this notice is maintained.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <limits.h>
static char *s_pMyName;
void usage(void);
int main(int argc, char *argv[])
{
char
sPath[PATH_MAX];
s_pMyName = strdup(basename(argv[0]));
if (argc < 2)
usage();
printf("%s\n", realpath(argv[1], sPath));
return 0;
}
void usage(void)
{
fprintf(stderr, "usage: %s PATH\n", s_pMyName);
exit(1);
}
Я не знаю, существует ли прямая команда удара, чтобы сделать это, но я обычно делаю
normalDir="`cd "${dirToNormalize}";pwd`"
echo "${normalDir}"
, и она работает хорошо.
Болтливый и немного запоздалый ответ. Мне нужно написать один, так как я застрял на более старом RHEL4 / 5. Я обрабатываю абсолютные и относительные ссылки и упрощаю записи //, /./ и somedir /../.
test -x /usr/bin/readlink || readlink () {
echo $(/bin/ls -l $1 | /bin/cut -d'>' -f 2)
}
test -x /usr/bin/realpath || realpath () {
local PATH=/bin:/usr/bin
local inputpath=$1
local changemade=1
while [ $changemade -ne 0 ]
do
changemade=0
local realpath=""
local token=
for token in ${inputpath//\// }
do
case $token in
""|".") # noop
;;
"..") # up one directory
changemade=1
realpath=$(dirname $realpath)
;;
*)
if [ -h $realpath/$token ]
then
changemade=1
target=`readlink $realpath/$token`
if [ "${target:0:1}" = '/' ]
then
realpath=$target
else
realpath="$realpath/$target"
fi
else
realpath="$realpath/$token"
fi
;;
esac
done
inputpath=$realpath
done
echo $realpath
}
mkdir -p /tmp/bar
(cd /tmp ; ln -s /tmp/bar foo; ln -s ../.././usr /tmp/bar/link2usr)
echo `realpath /tmp/foo`
Воспользуйтесь утилитой readlink из пакета coreutils.
MY_PATH=$(readlink -f "$0")
Переносимым и надежным решением является использование python, который предустановлен почти везде (включая Darwin). У вас есть два варианта:
abspath
возвращает абсолютный путь, но не разрешает символические ссылки:
python -c "import os, sys; print os.path.abspath (sys.argv [1])" path / to / file
realpath
возвращает абсолютный путь и при этом разрешает символические ссылки, генерируя канонический путь:
python -c "import os, sys; print os.path.realpath (sys.argv [ 1]) "путь / к / файлу
В каждом случае путь / к / файлу
может быть относительным или абсолютным путем.