Відповіді:
Ви можете скористатися readlink
утилітою з -f
можливістю:
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
Деякі дистрибутиви, наприклад ті, що використовують GNU coreutils та FreeBSD , також постачаються з realpath(1)
утилітою, яка в основному просто дзвінки realpath(3)
і робить майже те саме.
readlink
ні з realpath
Solaris та HP-UX, зокрема.
brew install coreutils
apple.stackexchange.com/a/69332/23040 , і якщо ви не хочете робити кроку, який перенаправляє всі стандартні інструменти Mac CLI до нещодавно встановлених еквівалентів GNU, просто зателефонуйте greadlink
.
Портативно, PWD
змінна встановлюється оболонкою в одне абсолютне місце поточного каталогу. Будь-який компонент цього шляху може бути символічним посиланням.
case $f in
/*) absolute=$f;;
*) absolute=$PWD/$f;;
esac
Якщо ви хочете усунути .
і, ..
також, перейдіть до каталогу, що містить файл, і знайдіть $PWD
там:
if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}
Немає портативного способу переходити до символічних посилань. Якщо у вас є шлях до каталогу, то в більшості уніцій $(cd -- "$dir" && pwd -P 2>/dev/null || pwd)
передбачений шлях, який не використовує символічні посилання, оскільки оболонки, які відстежують символьні посилання, як правило, реалізуються pwd -P
("P" для "фізичного").
Деякі унісеї надають утиліту для друку "фізичного" шляху до файлу.
readlink -f
, як і FreeBSD ≥8.3, NetBSD ≥4.0 та OpenBSD аж до 2.2.realpath
(він також присутній у деяких системах Linux, а також у BusyBox).Якщо Perl доступний, ви можете використовувати Cwd
модуль .
perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
pwd
( $(cd -- "$dir" && pwd -P 2>/dev/null | pwd)
)? Це, здається, не хвилює stdin.
||
Чи pwd
відповідає вашим потребам? Це дає абсолютний шлях поточного каталогу. А може, те, що ви хочете, це realpath () .
alister
і rss67
в цій статті представити найбільш стабільний, сумісний і найпростіший спосіб. Я ніколи не бачив кращого способу, ніж це раніше.
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
Якщо ви хочете повернутися до початкового місця,
ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH
або
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -
Я хочу, щоб це допомагало. Це було найбільшим рішенням для мене.
ABSPATH=$(cd -- "$RELPATH" && pwd)
. Зверніть увагу на подвійні лапки навколо підстановки (щоб не порушити, якщо шлях містить пробіли та символи глобусу) та --
(у випадку, якщо шлях починається з -
). Крім того, це працює лише для каталогів, і не канонізує символічні посилання за запитом. Дивіться мою відповідь для отримання більш детальної інформації.
Інші відповіді тут були чудовими, але були недостатніми для моїх потреб. Мені потрібно було рішення, яке я міг би використовувати в своїх сценаріях на будь-якій машині. Моє рішення полягало в тому, щоб написати скрипт оболонки, який я можу викликати із скриптів, де мені це потрібно.
#!/bin/sh
if [ $# -eq 0 ] || [ $# -gt 2 ]; then
printf 'Usage: respath path [working-directory]\n' >&2
exit 1
fi
cantGoUp=
path=$1
if [ $# -gt 1 ]; then
cd "$2"
fi
cwd=`pwd -P` #Use -P option to account for directories that are actually symlinks
#Handle non-relative paths, which don't need resolution
if echo "$path" | grep '^/' > /dev/null ; then
printf '%s\n' "$path"
exit 0
fi
#Resolve for each occurrence of ".." at the beginning of the given path.
#For performance, don't worry about ".." in the middle of the path.
while true
do
case "$path" in
..*)
if [ "$cwd" = '/' ]; then
printf 'Invalid relative path\n' >&2
exit 1
fi
if [ "$path" = '..' ]; then
path=
else
path=`echo "$path" | sed 's;^\.\./;;'`
fi
cwd=`dirname $cwd`
;;
*)
break
;;
esac
done
cwd=`echo "$cwd" | sed 's;/$;;'`
if [ -z "$path" ]; then
if [ -z "$cwd" ]; then
cwd='/'
fi
printf '%s\n' "$cwd"
else
printf '%s/%s\n' "$cwd" "$path"
fi
Це рішення написано для оболонки Борна для переносимості. Я маю це у сценарії під назвою "respath.sh".
Цей сценарій можна використовувати так:
respath.sh '/path/to/file'
Або так
respath.sh '/relative/path/here' '/path/to/resolve/relative/to'
Сценарій вирішує шлях у першому аргументі, використовуючи шлях від другого аргументу як вихідну точку. Якщо надається лише перший аргумент, то сценарій вирішує шлях відносно вашої поточної робочої каталоги.
pwd
вбудована і не підтримує -P
(оболонка Bourne не реалізувала таку логічну обробку $ PWD, як це роблять оболонки POSIX).
cd -P --
також і в разі першого аргументу містить деякі ..
case
чек має бути ..|../*)
замість ..*
.
dirname $cwd
Поважаючи відповідь усіх інших, я знайшов функцію нижче дуже легкою та портативною між Linux / MAC OSX, ніж інші, які я знаходив всюди. Може допомогти комусь.
#!/usr/bin/bash
get_absolute_path(){
file_path=`pwd $1`
echo "$file_path/$1"
}
#to assign to a variable
absolute_path=$(get_absolute_path "file.txt")
echo $absolute_path
Припустимо, змінна a зберігає назву шляху (a = "що завгодно")
1. Для потенційного вмісту, що містить простір:
c=$(grep -o " " <<< $a | wc -l); if (( $c > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi
2. Для власне питання, тобто перетворення шляху в абсолютний: readlink може отримати вміст симпосилання , яке можна використовувати наступним чином. (зауважте, readlink -f
це було б ідеально, але воно не доступне принаймні в басі Mac OS X, в якому -f означає FORMATS .)
if [[ $(readlink $a) == "" ]]; then a=$(cd $a; pwd); else a=$(cd $(readlink $a); pwd); fi
3. Тільки що дізналися pwd -P
в man pwd
: -P полягає в " Відображення фізичної поточної робочої директорії (всі символьні посилання вирішені) " і, отже
if (( $(grep -o " " <<< $a | wc -l) > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi; a=$(cd $a; pwd -P)
також працювати.
Висновок: комбінуйте 1 з 2, щоб задовольнити обидві ваші вимоги, тоді як назви пробірок, що містять простір, вже піклуються про більш стислі 3 .
-f
Перемикач не існує на Mac OS X (принаймні , за станом на 10.8.5). Без-f
комутатора він просто повертає код помилки.