realpathparece não estar disponível no Mac (OS X 10.11 "El Capitan"). :-(
Laringe Decidua
realpathtambém não parece estar disponível no CentOS 6
user5359531
6
no osx, brew install coreutilstrarárealpath
Kevin Chen
No meu Ubuntu 18.04, realpathjá está presente. Não precisei instalá-lo separadamente.
Acumenus 21/01/19
Surpreendentemente, realpathestá disponível no Git for Windows (pelo menos para mim).
Andrew Keeton
104
Se você tem o pacote coreutils instalado, geralmente pode usá-lo readlink -f relative_file_namepara recuperar o absoluto (com todos os links simbólicos resolvidos)
O comportamento para isso é um pouco diferente do que o usuário pede, ele também segue e resolve links simbólicos recursivos em qualquer lugar do caminho. Você pode não querer isso em alguns casos.
precisa saber é o seguinte
1
@BradPeabody Isso funciona em um Mac se você instalar o coreutils a partir do homebrew brew install coreutils. No entanto, o executável é prefixado por ag:greadlink -f relative_file_name
Miguel Isla
2
Observe que a página de manual do readlink (1) tem como primeira frase sua descrição: "Nota realpath (1) é o comando preferido para usar na funcionalidade de canonização".
Josch
1
você pode usar -e em vez de -f para verificar se o arquivo / diretório existe ou não
readlink é a solução simples para linux, mas esta solução funciona em OSX também, então +1
thetoolman
1
Este script não é equivalente ao que realpathou readlink -ffazer. Por exemplo, ele não funciona em caminhos nos quais o último componente é um link simbólico.
Josch
2
@josch: A questão não é sobre a resolução de links simbólicos. Mas se você quiser fazer isso você pode fornecer -Popção de pwdcomando:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Eugen Konkov
4
Eu gosto da resposta, mas só funciona se o usuário puder entrar no diretório. Isso nem sempre é possível.
Matthias B
34
Pelo que vale, votei na resposta que foi escolhida, mas queria compartilhar uma solução. A desvantagem é que é apenas o Linux - passei cerca de 5 minutos tentando encontrar o equivalente OSX antes de chegar ao Stack overflow. Tenho certeza de que está lá fora.
No Linux, você pode usar readlink -eem conjunto com dirname.
$(dirname $(readlink -e ../../../../etc/passwd))
rendimentos
/etc/
E então você usa dirnamea irmã de, basenamepara obter o nome do arquivo
Excelente entrada com dirname, readlinke basename. Isso me ajudou a obter o caminho absoluto de um link simbólico - não o seu alvo.
kevinarpe
Não funciona quando você deseja retornar o caminho para links simbólicos (o que eu preciso fazer ...).
Tomáš Zato - Reinstate Monica
Como você pode encontrar o caminho absoluto para um caminho que não existe?
Sintetizadorpatel
@synthesizerpatel Com bastante facilidade, eu teria pensado; se eu estiver /home/GKFXdigitando touch newfile, antes de pressionar enter, você poderá descobrir que eu quero dizer "create / home / GKFX / newfile", que é um caminho absoluto para um arquivo que ainda não existe.
GKFX 24/09
25
Eu acho que este é o mais portátil:
abspath(){
cd "$(dirname "$1")"
printf "%s/%s\n""$(pwd)""$(basename "$1")"
cd "$OLDPWD"}
Não há necessidade de gravar novamente. Consulte stackoverflow.com/a/21188136/1504556 . A sua é a melhor resposta nesta página, IMHO. Para os interessados, o link fornece uma explicação do motivo pelo qual essa solução funciona.
Peterh
Isso não é muito portátil, dirnameé um utilitário principal do GNU, não é comum a todos os unixen que acredito.
Oh meu Deus, obrigado. Eu tenho tentado corrigir a versão que usa ${1##*/}há um dia e agora que substituí o lixo por basename "$1"ele parece finalmente estar manipulando adequadamente os caminhos que terminam em /.
L3l_aze 28/08
NB, isso não faz a coisa certa com um caminho que termina em #../..
Alex Coventry
16
realpath provavelmente é melhor
Mas ...
A questão inicial era muito confusa, para começar, com um exemplo pouco relacionado à questão, conforme indicado.
A resposta selecionada, na verdade, responde ao exemplo dado, e não à pergunta do título. O primeiro comando é essa resposta (é mesmo? Duvido), e poderia funcionar tão bem sem o '/'. E não vejo o que o segundo comando está fazendo.
Vários problemas são mistos:
transformando um nome de caminho relativo em um absoluto, o que quer que ele denuncie, possivelmente nada. ( Normalmente, se você emitir um comando como touch foo/bar, o nome do caminho foo/bardeve existir para você e, possivelmente, ser usado na computação, antes que o arquivo seja realmente criado. )
pode haver vários nomes de caminho absolutos que denotam o mesmo arquivo (ou arquivo potencial), principalmente por causa de links simbólicos (links simbólicos) no caminho, mas possivelmente por outros motivos (um dispositivo pode ser montado duas vezes como somente leitura). Pode-se ou não querer resolver explicitamente esses links simbólicos.
chegando ao final de uma cadeia de links simbólicos para um arquivo ou nome sem vínculo simbólico. Isso pode ou não gerar um nome de caminho absoluto, dependendo de como é feito. E pode-se, ou não, querer resolvê-lo em um nome de caminho absoluto.
O comando readlink foosem opção fornece uma resposta apenas se o argumento foofor um link simbólico, e essa resposta for o valor desse link simbólico. Nenhum outro link é seguido. A resposta pode ser um caminho relativo: qualquer que seja o valor do argumento do link simbólico.
Contudo, readlink possui opções (-f -e ou -m) que funcionarão para todos os arquivos e fornecerão um nome de caminho absoluto (aquele sem links simbólicos) para o arquivo realmente indicado pelo argumento.
Isso funciona bem para qualquer coisa que não seja um link simbólico, embora se queira usar um nome de caminho absoluto sem resolver os links simbólicos intermediários no caminho. Isso é feito pelo comandorealpath -s foo
No caso de um argumento de link simbólico, readlinkcom suas opções novamente resolverá todos os links simbólicos no caminho absoluto para o argumento, mas isso também incluirá todos os links simbólicos que podem ser encontrados seguindo o valor do argumento. Você pode não querer isso se desejar um caminho absoluto para o próprio link simbólico do argumento, e não para o que quer que ele possa vincular. Novamente, se foofor um link simbólico, realpath -s fooobterá um caminho absoluto sem resolver links simbólicos, incluindo o fornecido como argumento.
Sem a -sopção, realpathfaz praticamente o mesmo que
readlink, exceto pela simples leitura do valor de um link, além de várias outras coisas. Simplesmente não está claro para mim por que readlinktem suas opções, criando aparentemente uma redundância indesejável com
realpath .
Explorar a web não diz muito mais, exceto que pode haver algumas variações entre os sistemas.
Conclusão: realpathé o melhor comando para usar, com a maior flexibilidade, pelo menos para o uso solicitado aqui.
Minha solução favorita foi a única do @EugenKonkov, porque não implicava a presença de outros utilitários (o pacote coreutils).
Mas falhou nos caminhos relativos "." e "..", então aqui está uma versão ligeiramente aprimorada que trata desses casos especiais.
Ele ainda falha se o usuário não tiver permissão para cdentrar no diretório pai do caminho relativo.
#! /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="$1"if["$target"=="."];then
echo "$(pwd)"elif["$target"==".."];then
echo "$(dirname "$(pwd)")"else
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"fi}
Se você estiver usando bash no Mac OS X, que não tem realpath existia nem a sua readlink pode imprimir o caminho absoluto, você pode ter escolha a não ser código sua própria versão para imprimi-lo. Aqui está a minha implementação:
(festança pura)
abspath(){local thePath
if[[!"$1"=~^/]];then
thePath="$PWD/$1"else
thePath="$1"fi
echo "$thePath"|(
IFS=/
read -a parr
declare -a outp
for i in"${parr[@]}";docase"$i"in''|.)continue;;..)
len=${#outp[@]}if((len==0));thencontinueelse
unset outp[$((len-1))]fi;;*)
len=${#outp[@]}
outp[$len]="$i";;esacdone
echo /"${outp[*]}")}
(use gawk)
abspath_gawk(){if[[-n "$1"]];then
echo $1|gawk '{
if(substr($0,1,1) != "/"){
path = ENVIRON["PWD"]"/"$0
} else path = $0
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}
Obrigado por este snippet de código, que pode fornecer ajuda limitada a curto prazo. Uma explicação adequada melhoraria bastante seu valor a longo prazo, mostrando por que essa é uma boa solução para o problema e a tornaria mais útil para futuros leitores com outras perguntas semelhantes. Por favor edite sua resposta para adicionar alguma explicação, incluindo as suposições que você fez.
precisa
1
Uma melhoria na versão bastante agradável do @ernest-a:
Isso lida corretamente com o caso em que está o último elemento do caminho ..; nesse caso, a "$(pwd)/$(basename "$1")"resposta do inernest-a será apresentada como accurate_sub_path/spurious_subdirectory/...
Em bash-4.3-p46, isso não funciona: a shell imprime uma linha em branco quando eu corrodir=`cd ".."` && echo $dir
Michael
0
Essa é uma solução encadeada de todas as outras, por exemplo, quando realpathfalha, ou porque não está instalada ou porque sai com o código de erro; então, a próxima solução é tentada até encontrar o caminho certo.
Não consegui encontrar uma solução que fosse perfeitamente portátil entre o Mac OS Catalina, o Ubuntu 16 e o Centos 7, por isso decidi fazê-lo com python inline e funcionou bem para meus scripts bash.
Respostas:
usar:
para obter todos os arquivos ou
para exibir o caminho completo (se o caminho relativo for importante)
fonte
$(pwd)
no lugar de$PWD
? (sim, eu sei quepwd
é um builtin)Tente
realpath
.Para evitar a expansão de links simbólicos, use
realpath -s
.A resposta vem do " comando bash / fish para imprimir o caminho absoluto para um arquivo ".
fonte
realpath
parece não estar disponível no Mac (OS X 10.11 "El Capitan"). :-(realpath
também não parece estar disponível no CentOS 6brew install coreutils
trarárealpath
realpath
já está presente. Não precisei instalá-lo separadamente.realpath
está disponível no Git for Windows (pelo menos para mim).Se você tem o pacote coreutils instalado, geralmente pode usá-lo
readlink -f relative_file_name
para recuperar o absoluto (com todos os links simbólicos resolvidos)fonte
brew install coreutils
. No entanto, o executável é prefixado por ag:greadlink -f relative_file_name
UPD Algumas explicações
"$1"
dirname "$1"
cd "$(dirname "$1")
nesse diretório relativo e obtemos o caminho absoluto para ele executando opwd
comando shell$(basename "$1")
echo
elefonte
realpath
oureadlink -f
fazer. Por exemplo, ele não funciona em caminhos nos quais o último componente é um link simbólico.-P
opção depwd
comando:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Pelo que vale, votei na resposta que foi escolhida, mas queria compartilhar uma solução. A desvantagem é que é apenas o Linux - passei cerca de 5 minutos tentando encontrar o equivalente OSX antes de chegar ao Stack overflow. Tenho certeza de que está lá fora.
No Linux, você pode usar
readlink -e
em conjunto comdirname
.rendimentos
E então você usa
dirname
a irmã de,basename
para obter o nome do arquivorendimentos
Coloque tudo junto ..
rendimentos
Você está seguro se estiver direcionando um diretório,
basename
não retornará nada e você acabará com duas barras na saída final.fonte
dirname
,readlink
ebasename
. Isso me ajudou a obter o caminho absoluto de um link simbólico - não o seu alvo./home/GKFX
digitandotouch newfile
, antes de pressionar enter, você poderá descobrir que eu quero dizer "create / home / GKFX / newfile", que é um caminho absoluto para um arquivo que ainda não existe.Eu acho que este é o mais portátil:
Falhará se o caminho ainda não existir.
fonte
dirname
é um utilitário principal do GNU, não é comum a todos os unixen que acredito.dirname
é um utilitário padrão do POSIX, consulte aqui: pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html${1##*/}
há um dia e agora que substituí o lixo porbasename "$1"
ele parece finalmente estar manipulando adequadamente os caminhos que terminam em /.../..
realpath
provavelmente é melhorMas ...
A questão inicial era muito confusa, para começar, com um exemplo pouco relacionado à questão, conforme indicado.
A resposta selecionada, na verdade, responde ao exemplo dado, e não à pergunta do título. O primeiro comando é essa resposta (é mesmo? Duvido), e poderia funcionar tão bem sem o '/'. E não vejo o que o segundo comando está fazendo.
Vários problemas são mistos:
transformando um nome de caminho relativo em um absoluto, o que quer que ele denuncie, possivelmente nada. ( Normalmente, se você emitir um comando como
touch foo/bar
, o nome do caminhofoo/bar
deve existir para você e, possivelmente, ser usado na computação, antes que o arquivo seja realmente criado. )pode haver vários nomes de caminho absolutos que denotam o mesmo arquivo (ou arquivo potencial), principalmente por causa de links simbólicos (links simbólicos) no caminho, mas possivelmente por outros motivos (um dispositivo pode ser montado duas vezes como somente leitura). Pode-se ou não querer resolver explicitamente esses links simbólicos.
chegando ao final de uma cadeia de links simbólicos para um arquivo ou nome sem vínculo simbólico. Isso pode ou não gerar um nome de caminho absoluto, dependendo de como é feito. E pode-se, ou não, querer resolvê-lo em um nome de caminho absoluto.
O comando
readlink foo
sem opção fornece uma resposta apenas se o argumentofoo
for um link simbólico, e essa resposta for o valor desse link simbólico. Nenhum outro link é seguido. A resposta pode ser um caminho relativo: qualquer que seja o valor do argumento do link simbólico.Contudo,
readlink
possui opções (-f -e ou -m) que funcionarão para todos os arquivos e fornecerão um nome de caminho absoluto (aquele sem links simbólicos) para o arquivo realmente indicado pelo argumento.Isso funciona bem para qualquer coisa que não seja um link simbólico, embora se queira usar um nome de caminho absoluto sem resolver os links simbólicos intermediários no caminho. Isso é feito pelo comando
realpath -s foo
No caso de um argumento de link simbólico,
readlink
com suas opções novamente resolverá todos os links simbólicos no caminho absoluto para o argumento, mas isso também incluirá todos os links simbólicos que podem ser encontrados seguindo o valor do argumento. Você pode não querer isso se desejar um caminho absoluto para o próprio link simbólico do argumento, e não para o que quer que ele possa vincular. Novamente, sefoo
for um link simbólico,realpath -s foo
obterá um caminho absoluto sem resolver links simbólicos, incluindo o fornecido como argumento.Sem a
-s
opção,realpath
faz praticamente o mesmo quereadlink
, exceto pela simples leitura do valor de um link, além de várias outras coisas. Simplesmente não está claro para mim por quereadlink
tem suas opções, criando aparentemente uma redundância indesejável comrealpath
.Explorar a web não diz muito mais, exceto que pode haver algumas variações entre os sistemas.
Conclusão:
realpath
é o melhor comando para usar, com a maior flexibilidade, pelo menos para o uso solicitado aqui.fonte
Minha solução favorita foi a única do @EugenKonkov, porque não implicava a presença de outros utilitários (o pacote coreutils).
Mas falhou nos caminhos relativos "." e "..", então aqui está uma versão ligeiramente aprimorada que trata desses casos especiais.
Ele ainda falha se o usuário não tiver permissão para
cd
entrar no diretório pai do caminho relativo.fonte
A resposta de Eugen não funcionou muito bem para mim, mas isso fez:
Nota lateral, seu diretório de trabalho atual não é afetado.
fonte
A melhor solução, imho, é a postada aqui: https://stackoverflow.com/a/3373298/9724628 .
Requer python para funcionar, mas parece cobrir todos ou quase todos os casos extremos e é uma solução muito portátil.
fonte
No caso de
find
, provavelmente é mais fácil fornecer apenas o caminho absoluto para a pesquisa, por exemplo:fonte
Se você estiver usando bash no Mac OS X, que não tem realpath existia nem a sua readlink pode imprimir o caminho absoluto, você pode ter escolha a não ser código sua própria versão para imprimi-lo. Aqui está a minha implementação:
(festança pura)
(use gawk)
(puro bsd awk)
exemplo:
fonte
O que eles disseram, exceto
find $PWD
ou (no bash),find ~+
é um pouco mais conveniente.fonte
Semelhante à resposta do @ernest-a, mas sem afetar
$OLDPWD
ou definir uma nova função, você pode disparar um subshell(cd <path>; pwd)
fonte
Se o caminho relativo for um caminho de diretório, tente o meu, deve ser o melhor:
fonte
fonte
Uma melhoria na versão bastante agradável do @ernest-a:
Isso lida corretamente com o caso em que está o último elemento do caminho
..
; nesse caso, a"$(pwd)/$(basename "$1")"
resposta do inernest-a será apresentada comoaccurate_sub_path/spurious_subdirectory/..
.fonte
Se você deseja transformar uma variável que contém um caminho relativo em absoluto, isso funciona:
"cd" ecoa sem alterar o diretório de trabalho, porque executado aqui em um sub-shell.
fonte
dir=`cd ".."` && echo $dir
Essa é uma solução encadeada de todas as outras, por exemplo, quando
realpath
falha, ou porque não está instalada ou porque sai com o código de erro; então, a próxima solução é tentada até encontrar o caminho certo.fonte
Você pode usar a substituição do string bash para qualquer caminho relativo $ line:
A substituição básica da frente de cadeia segue a fórmula
$ {string / # substring / Replacement}
que é discutida aqui: https://www.tldp.org/LDP/abs/html/string-manipulation.html
O
\
caractere nega/
quando queremos que ele faça parte da string que encontramos / substituímos.fonte
Não consegui encontrar uma solução que fosse perfeitamente portátil entre o Mac OS Catalina, o Ubuntu 16 e o Centos 7, por isso decidi fazê-lo com python inline e funcionou bem para meus scripts bash.
fonte