Баш: возвращает абсолютный путь относительно
есть ли команда для получения абсолютного пути, заданного относительным путем?
например, я хочу, чтобы $line содержал абсолютный путь к каждому файлу в dir ./etc/
find ./ -type f | while read line; do
echo $line
done
16 ответов
использование:
find $(pwd)/ -type f
чтобы получить все файлы или
echo $(pwd)/$line
для отображения полного пути (если относительный путь имеет значение)
попробовать realpath
.
~ $ sudo apt-get install realpath
~ $ realpath .bashrc
/home/username/.bashrc
ответ приходит от "команда bash/fish для печати абсолютного пути к файлу".
Если у вас установлен пакет coreutils, вы обычно можете использовать readlink -f relative_file_name
для получения абсолютного (все симлинки решен)
#! /bin/sh
echo "$(cd "$(dirname "")"; pwd)/$(basename "")"
UPD объяснения
- этот скрипт получает относительный путь в качестве аргумента
""
- тогда мы получим dirname часть этого пути (вы можете передать либо dir, либо файл в этот скрипт):
dirname ""
- затем мы
cd "$(dirname "")
в этот относительный dir и получить абсолютный путь для него, запустивpwd
shell command - после этого мы добавляем имени к абсолютному пути:
$(basename "")
- в качестве заключительного шага мы
echo
это
для чего это стоит, Я проголосовал за ответ, который был выбран, но хотел поделиться решением. Недостатком является то, что это только Linux - я потратил около 5 минут, пытаясь найти эквивалент OSX, прежде чем перейти к переполнению стека. Но я уверен, что он где-то там.
в Linux вы можете использовать readlink -e
вместе с dirname
.
$(dirname $(readlink -e ../../../../etc/passwd))
доходность
/etc/
и dirname
С сестрой basename
просто
этот именем
$(basename ../../../../../passwd)
доходность
passwd
сложите все вместе..
F=../../../../../etc/passwd
echo "$(dirname $(readlink -e $F))/$(basename $F)"
доходность
/etc/passwd
вы в безопасности, если вы нацелены на каталог,basename
ничего не вернуть
и вы просто закончите с двойными косыми чертами в конечном выходе.
Я думаю, что это самый портативный:
abspath() {
cd "$(dirname "")"
printf "%s/%s\n" "$(pwd)" "$(basename "")"
cd "$OLDPWD"
}
он потерпит неудачу, если путь не существует.
realpath
лучше
но ...
начальный вопрос был очень запутан для начала, с примером плохо связано с вопросом, как указано.
выбранный ответ фактически отвечает приведенному примеру, а не вообще вопрос в названии. Первая команда-это ответ (is it неужели ? Я сомневаюсь), и мог бы обойтись и без"/". И я не вижу что делает вторая команда.
несколько вопросов смешанный:
изменение относительного пути в абсолютный, что бы это ни было обозначает, возможно, ничего. (обычно, если вы выдаете команду, такую как
touch foo/bar
, в путьfoo/bar
должен существовать для вас, и, возможно, будут использоваться в вычисление, прежде чем файл будет создан.)может быть несколько абсолютных путей, которые обозначают один и тот же файл (или потенциальный файл), в частности, из-за символических ссылок (символических ссылок) На путь, но, возможно, по другим причинам (устройство может быть монтируется дважды как только для чтения). Можно или не нужно решать явно такие симлинки.
переход к концу цепочки символических ссылок на несимметричную ссылку файл или имя. Это может дать или не дать абсолютное имя пути, в зависимости от того, как это делается. И можно, а можно и не хотеть. разрешите его в абсолютный путь.
команда readlink foo
без опции дает ответ только если его
аргумент foo
является символической ссылкой, и этот ответ является значением этого
символьная ссылка. Никакой другой ссылки не следует. Ответ может быть относительным путем:
независимо от значения аргумента symlink.
однако, readlink
имеет опции (- f-e или-m), которые будут работать для всех
файлы и дать один абсолютный путь (тот, у которого нет символических ссылок) к
файл фактически обозначается аргументом.
это прекрасно работает для всего, что не является символической ссылкой, если можно
жаждать использование абсолютного пути без разрешения промежуточного
символические ссылки на пути. Это делается командой realpath -s foo
в случае, если аргумент ссылки readlink
С его варианты
опять решать все ссылки на абсолютный путь к аргументу, но
это также будет включать все символические ссылки, с которыми могут столкнуться
после значения аргумента. Вы можете не хотеть этого, если вы хотите
абсолютный путь к аргументу симлинк себе, нежели любой
это может быть связано. Опять же, если foo
является символической ссылкой,realpath -s foo
будет
получить абсолютный путь без разрешения символических ссылок, в том числе
приведено в качестве аргумента.
без , realpath
делает почти то же самое, что и
readlink
, за исключением просто чтения значения ссылки, а также нескольких
прочие вещи. Мне просто непонятно, почему readlink
имеет
варианты, создавая, по-видимому, нежелательную избыточность с
realpath
.
изучение интернета не говорит намного больше, за исключением что там может быть некоторые различия между системами.
вывод : realpath
является лучшей командой для использования, с наиболее
гибкость, по крайней мере для использования здесь.
ответ Ойгена не совсем сработал для меня, но это:
absolute="$(cd $(dirname $file); pwd)/$(basename $file)"
Примечание, ваш текущий рабочий каталог не изменяется.
в случае find
, вероятно, проще всего просто дать абсолютный путь для его поиска, например:
find /etc
find `pwd`/subdir_of_current_dir/ -type f
если вы используете bash на Mac OS X, который ни имеет реального пути существовал, ни его более ранних версий можно напечатать абсолютный путь, у вас может быть выбор, но закодировать свою собственную версию для печати. Вот моя реализация:
(чисто Баш)
abspath(){
local thePath
if [[ ! "" =~ ^/ ]];then
thePath="$PWD/"
else
thePath=""
fi
echo "$thePath"|(
IFS=/
read -a parr
declare -a outp
for i in "${parr[@]}";do
case "$i" in
''|.) continue ;;
..)
len=${#outp[@]}
if ((len==0));then
continue
else
unset outp[$((len-1))]
fi
;;
*)
len=${#outp[@]}
outp[$len]="$i"
;;
esac
done
echo /"${outp[*]}"
)
}
(используйте gawk)
abspath_gawk() {
if [[ -n "" ]];then
echo |gawk '{
if(substr(,1,1) != "/"){
path = ENVIRON["PWD"]"/"
} else path =
split(path, a, "/")
n = asorti(a, b,"@ind_num_asc")
for(i in a){
if(a[i]=="" || a[i]=="."){
delete a[i]
}
}
n = asorti(a, b, "@ind_num_asc")
m = 0
while(m!=n){
m = n
for(i=1;i<=n;i++){
if(a[b[i]]==".."){
if(b[i-1] in a){
delete a[b[i-1]]
delete a[b[i]]
n = asorti(a, b, "@ind_num_asc")
break
} else exit 1
}
}
}
n = asorti(a, b, "@ind_num_asc")
if(n==0){
printf "/"
} else {
for(i=1;i<=n;i++){
printf "/"a[b[i]]
}
}
}'
fi
}
(чистый BSD awk)
#!/usr/bin/env awk -f
function abspath(path, i,j,n,a,b,back,out){
if(substr(path,1,1) != "/"){
path = ENVIRON["PWD"]"/"path
}
split(path, a, "/")
n = length(a)
for(i=1;i<=n;i++){
if(a[i]==""||a[i]=="."){
continue
}
a[++j]=a[i]
}
for(i=j+1;i<=n;i++){
delete a[i]
}
j=0
for(i=length(a);i>=1;i--){
if(back==0){
if(a[i]==".."){
back++
continue
} else {
b[++j]=a[i]
}
} else {
if(a[i]==".."){
back++
continue
} else {
back--
continue
}
}
}
if(length(b)==0){
return "/"
} else {
for(i=length(b);i>=1;i--){
out=out"/"b[i]
}
return out
}
}
BEGIN{
if(ARGC>1){
for(k=1;k<ARGC;k++){
print abspath(ARGV[k])
}
exit
}
}
{
print abspath()
}
пример:
$ abspath I/am/.//..//the/./god/../of///.././war
/Users/leon/I/the/war
моим любимым решением было один @EugenKonkov, потому что это не подразумевало наличие других утилит (пакет coreutils).
но это не для относительных путей "." и." ."так вот немного улучшенная версия обработки этих особых случаях.
Он все еще терпит неудачу, если у пользователя нет разрешения на в родительский каталог относительного пути.
#! /bin/sh
# Takes a path argument and returns it as an absolute path.
# No-op if the path is already absolute.
function to-abs-path {
local target=""
if [ "$target" == "." ]; then
echo "$(pwd)"
elif [ "$target" == ".." ]; then
echo "$(dirname "$(pwd)")"
else
echo "$(cd "$(dirname "")"; pwd)/$(basename "")"
fi
}
похоже на ответ @ernest-a, но без влияния $OLDPWD
или определите новую функцию, которую вы можете запустить subshell (cd <path>; pwd)
$ pwd
/etc/apache2
$ cd ../cups
$ cd -
/etc/apache2
$ (cd ~/..; pwd)
/Users
$ cd -
/etc/cups
Если относительный путь является путем каталога, то попробуйте мой, должен быть лучшим:
absPath=$(pushd ../SOME_RELATIVE_PATH_TO_Directory > /dev/null && pwd && popd > /dev/null)
echo $absPath
Если вы хотите преобразовать переменную, содержащую относительный путь в абсолютный, это работает :
dir=`cd "$dir"`
" cd " Эхо без изменения рабочего каталога, потому что выполняется здесь в под-оболочке.
echo "mydir/doc/ mydir/usoe ./mydir/usm" | awk '{ split(,array," "); for(i in array){ system("cd "array[i]" && echo $PWD") } }'