Відповіді:
Ви можете скористатися readlinkутилітою з -fможливістю:
-f, --canonicalizecanonicalize 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ні з realpathSolaris та 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/filepwd( $(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комутатора він просто повертає код помилки.