Como obter o caminho completo do arquivo original de um link simbólico suave?

99

Eu quero scpum arquivo para um servidor. O arquivo é um link simbólico e, na verdade, o que eu quero fazer é copiar o arquivo de origem. De qualquer forma, não quero rastrear o caminho do arquivo de origem manualmente, porque ele pode ser substituído. Se eu posso obter o caminho absoluto do arquivo de origem, posso obtê- seplo. Como posso pegar o caminho?

Eonil
fonte
2
A maioria das scpversões segue links simbólicos por padrão, não é? Você deve verificar o seu e talvez poupar algum trabalho.
jw013
@ jw103 Obrigado por me informar. Eu não sabia :)
Eonil
2
Nota: scp -rforça o seguinte link simbólico.
Eonil

Respostas:

129

Tente esta linha:

readlink -f `which command`

Se commandestiver na sua $PATHvariável, caso contrário, você precisará especificar o caminho que conhece.

margarida
fonte
12
-fretornará um caminho para um destino final inexistente, desde que os destinos do link intermediário existam ... Use -epara evitar isso, por exemplo. -eretornará nulo se o destino final não existir.
Peter.O
10
-fcom erro readlink: illegal option -- fno OSX. Removê-lo funcionou bem.
Heath Borders
2
@HeathBorders Para OSX, se você tiver o coreutils de homebrew instalado, também poderá usar greadlink.
Adam Gent
23

No Linux, readlinklê o conteúdo de um link simbólico e readlink -fsegue links simbólicos para links simbólicos etc., até encontrar algo que não seja um link simbólico.

Porém, isso não é necessário para o scp: o scp sempre segue links simbólicos (ele sempre copia o conteúdo do arquivo, ignorando os metadados, exceto que -ppreserva os tempos e modos do arquivo, quando possível).

Se você se decepcionar com o que os metadados scp podem e não podem preservar, sugiro usar o rsync. Sem opção, o rsync copia o conteúdo do arquivo ignorando os metadados. A opção comumente usada -apreserva todos os metadados de variedade de jardim (horários, links simbólicos, permissões e propriedade) e existem opções para preservar metadados exóticos, como ACLs e links físicos.

Gilles
fonte
O readlink faz apenas uma etapa para o link de leitura. por exemplo, no ubuntu, temos / bin / zsh, vinculado ao / etc / alternative / zsh, mas este é o segundo link simbólico. Finalmente, não obteremos o caminho real do arquivo ou diretório. O mesmo é com o comando stat. Somente o readlink com a opção -f faz todas as resoluções.
Znik 23/03
9

Eu uso de comando ls, stat, readlink.

Tome o arquivo /etc/localtimecomo um exemplo

[flying@lempstacker ~]$ ls /etc/localtime 
/etc/localtime
[flying@lempstacker ~]$ ls -l /etc/localtime
lrwxrwxrwx. 1 root root 35 Aug  2 22:41 /etc/localtime -> ../usr/share/zoneinfo/Asia/Shanghai

Operação

Usando stat

[flying@lempstacker ~]$ stat /etc/localtime
  File: ‘/etc/localtime’ -> ‘../usr/share/zoneinfo/Asia/Shanghai’
  Size: 35          Blocks: 0          IO Block: 4096   symbolic link
Device: fd01h/64769d    Inode: 272202388   Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2016-11-23 09:00:59.999887800 +0800
Modify: 2016-08-02 22:41:26.090389904 +0800
Change: 2016-08-02 22:41:26.090389904 +0800
 Birth: -
[flying@lempstacker ~]$ stat -c "%N" /etc/localtime
‘/etc/localtime’ -> ‘../usr/share/zoneinfo/Asia/Shanghai’

Usando o readlink

[flying@lempstacker ~]$ readlink /etc/localtime
../usr/share/zoneinfo/Asia/Shanghai
[flying@lempstacker ~]$ readlink -f /etc/localtime
/usr/share/zoneinfo/Asia/Shanghai

Parece que esse comando readlink -fé melhor.

Explicação

-f, --canonicalize: canonicalize seguindo cada link simbólico em cada componente do nome fornecido recursivamente; todos, exceto o último componente, devem existirman readlink

Gorgon
fonte
6

O Stat fornecerá essas informações:

$ stat current
  File: `current' -> `/home/user/releases/build/'
  ...
polinomial
fonte
O readlink faz apenas uma etapa para o link de leitura. por exemplo, no ubuntu, temos / bin / zsh, vinculado ao / etc / alternative / zsh, mas este é o segundo link simbólico. Finalmente, não obteremos o caminho real do arquivo ou diretório. O mesmo é com o comando stat. Somente o readlink com a opção -f faz todas as resoluções.
Znik 23/03
5

Você pode fazer

readlink -f `which command`

ou você pode obter algo semelhante no Linux com

stat `which command` | grep File

Se você estiver adicionando isso a um script, inspecione o erro. Se você não quiser ver a mensagem de erro no caso em que o link sym não estiver lá, escolha algo como

readlink -f "`which command`" 
Alexandre Santos
fonte
stat e realink sem -f executam apenas uma etapa. então é melhor chamar readlink -f.
Znik 23/03
3

Eu usaria realpath <symlink>.

Provavelmente o que você chama de 'origem' é o arquivo 'destino' de acordo com o uso de ln:Usage: ln [OPTION]... [-T] TARGET LINK_NAME

XavierStuvw
fonte
Obrigado Isso funcionou como um encanto! com o Mac OSX! onde readlinknão cortou ... mac estúpido. lol
JayRizzo
0

readlink -f 'which java' não funcionou para mim.

Mas isso fez:

readlink -f $(which java)
NonCreature0714
fonte
3
Não funcionou porque é `não '.. mas $()é melhor prática de qualquer maneira.
Stephen Rauch
Por que voto negativo? Minha resposta é uma alternativa aceitável e, como diz o comentário, uma melhor prática.
NonCreature0714
1
A maioria das pessoas que votam negativamente também não comenta, portanto, pedir uma explicação de voto negativo raramente lhe dará uma explicação, porque o eleitor que já recusou já saiu e provavelmente não voltará. Eu sugiro que você remova o código digitado que não funciona da sua resposta. Eu estaria disposto a votar se você tivesse tempo para limpá-lo e explicar por que $()é uma prática melhor.
Stephen Rauch
Como Stephen explicou a você, 'não é'. Você deve encapsular por command, mas isso foi preterido. usar $ () é melhor, porque o encapsulamento $ ($ (command)) é muito mais fácil e não precisa de escape especial. Então é preferido. No seu primeiro exemplo, você usou o apóstrofo usual, e o readlink está tentando encontrar o arquivo chamado 'what java' com espaço em seu nome. Mas sua intenção é chamar o comando que, com o argumento java, para encontrar o caminho executável binário do java.
Znik 23/03
0

No MAC OX, o parâmetro "-f" não funciona, o 'readlink' funciona sem nenhum parâmetro.

KZs-MacBook-Pro:bin kz$ readlink -f pip3
readlink: illegal option -- f
usage: readlink [-n] [file ...]

KZs-MacBook-Pro:bin kz$ readlink pip3
../../../Library/Frameworks/Python.framework/Versions/3.7/bin/pip3
Xb74Dkjb
fonte