No Linux, o readlink
utilitário aceita uma opção -f
que segue links adicionais. Isso não parece funcionar em sistemas Mac e possivelmente baseados em BSD. Qual seria o equivalente?
Aqui estão algumas informações de depuração:
$ which readlink; readlink -f
/usr/bin/readlink
readlink: illegal option -f
usage: readlink [-n] [file ...]
readlink
pode ser um comando interno ou externo.touch myfile ; ln -s myfile otherfile ; perl -MCwd=abs_path -le 'print abs_path readlink(shift);' otherfile
... no meu caso, vejo: / Users / cito / myfile`. Adicionado à minha resposta abaixo. Felicidades.Respostas:
readlink -f
faz duas coisas:Se desejar, basta criar um script de shell que use o comportamento de vanilla readlink para conseguir a mesma coisa. Aqui está um exemplo. Obviamente, você pode inserir isso em seu próprio script, onde gostaria de chamar
readlink -f
Observe que isso não inclui nenhum tratamento de erros. De particular importância, ele não detecta ciclos de vínculo simbólico. Uma maneira simples de fazer isso seria contar o número de vezes que você percorre o loop e falha se atingir um número improvávelmente grande, como 1.000.
EDITADO para usar em
pwd -P
vez de$PWD
.Note que este script espera ser chamado como
./script_name filename
, não-f
, mude$1
para$2
se você quiser usar com o-f filename
GNU readlink.fonte
foo -> /var/cux
, entãofoo/bar
não será resolvido, porquebar
não é um link, emborafoo
seja.cd "$(dirname "$TARGET_FILE")"
eTARGET_FILE=$(readlink "$TARGET_FILE")
eTARGET_FILE=$(basename "$TARGET_FILE")
nos lugares apropriados no código acima.MacPorts e Homebrew fornecem um pacote coreutils contendo
greadlink
(GNU readlink). Crédito para Michael Kallweitt post no mackb.com.fonte
.bashrc
:export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
pwd -P
ereadlink
no OS X, sem instalar nadaPATH
. Fiz o que foi dito acima começando combrew install <package> --default-names
. Muitas vezes, uma pergunta neste site foi respondida levemente, ou mais, fora dos requisitos técnicos do solicitante, mas dentro de uma situação semelhante e ainda tem sido muito útil. topbug.net/blog/2013/04/14/…Você pode estar interessado
realpath(3)
ou no Pythonos.path.realpath
. Os dois não são exatamente iguais; a chamada da biblioteca C requer a existência de componentes do caminho intermediário, enquanto a versão do Python não.Eu sei que você disse que preferiria algo mais leve do que outra linguagem de script, mas, caso compile um binário seja insuportável, você pode usar Python e ctypes (disponíveis no Mac OS X 10.5) para encerrar a chamada da biblioteca:
Ironicamente, a versão C deste script deve ser mais curta. :)
fonte
realpath
é realmente o que eu quero. Mas parece bastante estranho que eu tenha que compilar um binário para obter essa função de um script de shell.readlink
si mesmo, não é?)python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" "${1}"
trabalha com caminhos como'~/.symlink'
perl -MCwd=abs_path -le 'print abs_path readlink(shift);'
à minha resposta :-)Eu odeio continuar com outra implementação, mas eu precisava de a) uma implementação de shell portátil e pura eb) cobertura de teste de unidade , pois o número de casos extremos para algo assim não é trivial .
Veja meu projeto no Github para testes e código completo. A seguir, é apresentada uma sinopse da implementação:
Como Keith Smith astuciosamente aponta,
readlink -f
faz duas coisas: 1) resolve os links simbólicos de forma recursiva e 2) canoniza o resultado, portanto:Primeiro, a implementação do resolvedor de link simbólico:
Observe que esta é uma versão ligeiramente simplificada da implementação completa . A implementação completa adiciona uma pequena verificação de ciclos de link simbólico , além de massagear um pouco a saída.
Finalmente, a função para canonizar um caminho:
É isso, mais ou menos. Simples o suficiente para colar em seu script, mas complicado o suficiente para que você seja louco por confiar em qualquer código que não tenha testes de unidade para seus casos de uso.
fonte
local
palavra-chavereadlink -f
, nem derealpath
. Supondo que um Mac com a fórmula coreutils instalada (portanto, comgreadlink
disponível), tente fazer isso comln -s /tmp/linkeddir ~/Documents
;greadlink -f /tmp/linkeddir/..
imprime seu diretório pessoal (ele resolveu o/tmp/linkeddir
link antes de aplicar a..
dir dir pai), mas seu código produz/private/tmp/
como/tmp/linkeddir/..
não é um link simbólico, mas-d /tmp/linkeddir/..
é verdadeiro ecd /tmp/linkeddir/..
leva você a/tmp
cujo caminho canônico é/private/tmp
. Seu código faz o querealpath -L
faz, em vez disso.Um one-liner simples em perl que certamente funcionará em quase todos os lugares sem dependências externas:
Desreferirá links simbólicos.
O uso em um script pode ser assim:
fonte
-l
, comoperl -MCwd -le 'print Cwd::abs_path shift' ~/non-absolute/file
O greadlink é o gnu readlink que implementa -f. Você pode usar macports ou outros também, eu prefiro homebrew.
fonte
Eu criei um script chamado realpath pessoalmente que se parece um pouco com:
fonte
sys.argv[1]
se desejar que o script imprima o caminho real do primeiro argumento.sys.argv[0]
apenas imprime o caminho real do próprio script pyton, o que não é muito útil.~/.profile
:alias realpath="python -c 'import os, sys; print os.path.realpath(sys.argv[1])'"
readlink -f
, aqui está uma versão modificada do alias de @jwhitlock para oferecer suporte a possíveis-f
sinalizadores:alias realpath="python -c 'import os, sys; print os.path.realpath(sys.argv[2] if sys.argv[1] == \"-f\" else sys.argv[1])'"
Que tal isso?
fonte
../../../
->/
/usr/bin/
por exemplo, como oalternatives
sistema gosta de ter.Aqui está uma função de shell portátil que deve funcionar em QUALQUER shell comparável da Bourne. Ele resolverá a pontuação do caminho relativo ".. ou". e links simbólicos de desreferência.
Se, por algum motivo, você não tiver um comando realpath (1) ou o readlink (1), este poderá ser um alias.
Aproveitar:
Além disso, no caso de alguém estar interessado aqui, é como implementar o nome da base e o nome do diretório no código shell 100% puro:
Você pode encontrar a versão atualizada deste código de shell no meu site do google: http://sites.google.com/site/jdisnard/realpath
EDIT: Este código está licenciado sob os termos da licença de 2 cláusulas (estilo FreeBSD). Uma cópia da licença pode ser encontrada seguindo o link acima para o meu site.
fonte
O FreeBSD e OSX têm uma versão do
stat
derivada do NetBSD.Você pode ajustar a saída com opções de formato (consulte as páginas de manual nos links acima).
Algumas versões do OS X
stat
podem não ter a-f%R
opção de formatos. Nesse caso,-stat -f%Y
pode ser suficiente. A-f%Y
opção mostrará o destino de um link simbólico, enquanto-f%R
mostra o nome do caminho absoluto correspondente ao arquivo.EDITAR:
Se você puder usar o Perl (o Darwin / OS X vem instalado com versões recentes de
perl
), então:vai funcionar.
fonte
R
opção para-f%
está ausente. Possivelmentestat -f%Y
fornece a saída desejada. Eu ajustarei a resposta. Observe que astat
ferramenta apareceu no FreeBSD na versão 4.10 e no NetBSD na versão 1.6.A maneira mais fácil de resolver esse problema e ativar a funcionalidade do readlink no Mac com Homebrew instalado ou no FreeBSD é instalar o pacote 'coreutils'. Também pode ser necessário em certas distribuições Linux e em outros sistemas operacionais POSIX.
Por exemplo, no FreeBSD 11, instalei invocando:
# pkg install coreutils
No MacOS com Homebrew, o comando seria:
$ brew install coreutils
Não sei ao certo por que as outras respostas são tão complicadas, isso é tudo. Os arquivos não estão em um local diferente, eles ainda não estão instalados.
fonte
brew install coreutils --with-default-names
para ser mais específico. Ou você vai acabar com "greadlink" em vez ...pwd -P
é bastante simples, mas desaparece entre muitas outras respostas, incluindo repetidas, daí o voto negativo.Iniciar atualização
Esse é um problema tão frequente que reunimos uma biblioteca do Bash 4 para uso gratuito (MIT License) chamada realpath-lib . Isso foi projetado para emular o readlink -f por padrão e inclui dois conjuntos de testes para verificar (1) se ele funciona para um determinado sistema unix e (2) contra o readlink -f se instalado (mas isso não é necessário). Além disso, ele pode ser usado para investigar, identificar e desabilitar links simbólicos profundos e quebrados e referências circulares, para que possa ser uma ferramenta útil para diagnosticar problemas físicos ou simbólicos e aninhados de diretórios e arquivos físicos ou profundamente aninhados. Pode ser encontrado em github.com ou bitbucket.org .
Finalizar atualização
Outra solução muito compacta e eficiente que não depende de nada além do Bash é:
Isso também inclui uma configuração de ambiente
no_symlinks
que fornece a capacidade de resolver links simbólicos para o sistema físico. Desde queno_symlinks
esteja definido como algo, ou seja,no_symlinks='on'
, os links simbólicos serão resolvidos para o sistema físico. Caso contrário, eles serão aplicados (a configuração padrão).Isso deve funcionar em qualquer sistema que forneça o Bash e retornará um código de saída compatível com o Bash para fins de teste.
fonte
Já existem muitas respostas, mas nenhuma funcionou para mim ... Então é isso que estou usando agora.
fonte
$target
for um caminho, só funciona se for um arquivo.Uma maneira preguiçosa que funciona para mim,
fonte
Antes tarde do que nunca, suponho. Eu estava motivado a desenvolver isso especificamente porque meus scripts do Fedora não estavam funcionando no Mac. O problema é dependências e Bash. Os Macs não os possuem ou, se o possuem, geralmente estão em outro lugar (outro caminho). A manipulação do caminho de dependência em um script Bash entre plataformas é, na melhor das hipóteses, uma dor de cabeça e, na pior das hipóteses, um risco de segurança - por isso, é melhor evitar o uso, se possível.
A função get_realpath () abaixo é simples, centrada no Bash e nenhuma dependência é necessária. Eu uso apenas o Bash builtins eco e cd . Também é bastante seguro, pois tudo é testado em cada estágio do caminho e retorna condições de erro.
Se você não quiser seguir os links simbólicos, coloque set -P na frente do script, mas, caso contrário, o cd deverá resolver os links simbólicos por padrão. Foi testado com argumentos de arquivo que são {absolute | parente | link simbólico | local} e retorna o caminho absoluto para o arquivo. Até agora, não tivemos problemas com isso.
Você pode combinar isso com outras funções get_dirname, get_filename, get_stemname e validate_path. Estes podem ser encontrados em nosso repositório GitHub como realpath-lib (divulgação completa - este é o nosso produto, mas o oferecemos gratuitamente à comunidade, sem restrições). Também poderia servir como uma ferramenta instrucional - está bem documentada.
Tentamos o nosso melhor para aplicar as chamadas práticas 'modernas do Bash', mas o Bash é um grande assunto e tenho certeza de que sempre haverá espaço para melhorias. Requer o Bash 4+, mas pode ser feito para funcionar com versões mais antigas, se ainda estiverem por aí.
fonte
Como meu trabalho é usado por pessoas com Linux não BSD e com o macOS, optei por usar esses aliases em nossos scripts de construção (
sed
incluídos por apresentar problemas semelhantes):Verificação opcional que você pode adicionar para instalar automaticamente as dependências do homebrew + coreutils :
Suponho que, para ser verdadeiramente "global", é necessário verificar os outros ... mas isso provavelmente chega perto da marca 80/20.
fonte
Explicação
O coreutils é um
brew
pacote que instala os principais utilitários do GNU / Linux, que correspondem à implementação do Mac OSX para que você possa usá-los.Você pode encontrar programas ou utilitários no sistema mac osx que parecem semelhantes aos coreutils do Linux ("Utilitários Principais"), mas eles diferem em alguns aspectos (como ter sinalizadores diferentes).
Isso ocorre porque a implementação do Mac OSX dessas ferramentas é diferente. Para obter o comportamento original do GNU / Linux, você pode instalar o
coreutils
pacote através dobrew
sistema de gerenciamento de pacotes.Isso instalará os principais utilitários correspondentes, prefixados por
g
. Por exemploreadlink
, para , você encontrará umgreadlink
programa correspondente .Para ter um
readlink
desempenho semelhante à implementação GNUreadlink
(greadlink
), você pode criar um alias simples depois de instalar o coreutils.Implementação
Siga as instruções em https://brew.sh/
brew install coreutils
Você pode colocar seu alias em ~ / .bashrc, ~ / .bash_profile ou onde quer que esteja acostumado a manter seus aliases de bash. Pessoalmente, mantenho o meu em ~ / .bashrc
alias readlink=greadlink
Você pode criar aliases semelhantes para outros coreutils, como gmv, gdu, gdf e assim por diante. Mas lembre-se de que o comportamento do GNU em uma máquina Mac pode ser confuso para outras pessoas acostumadas a trabalhar com coreutils nativos ou pode se comportar de maneiras inesperadas no seu sistema Mac.
fonte
Eu escrevi um utilitário realpath para o OS X que pode fornecer os mesmos resultados que
readlink -f
.Aqui está um exemplo:
Se você estiver usando MacPorts, você pode instalá-lo com o seguinte comando:
sudo port selfupdate && sudo port install realpath
.fonte
Verdadeiramente independente da plataforma também seria esse R-onliner
Para realmente imitar
readlink -f <path>
, $ 2 em vez de $ 1 precisariam ser usados.fonte
readlink -f
Implementação compatível com POSIX para scripts de shell POSIXhttps://github.com/ko1nksm/readlinkf
Isso é compatível com POSIX (sem basismo). Não usa nem
readlink
nemrealpath
. Eu verifiquei que é exatamente o mesmo comparando com o GNUreadlink -f
(consulte os resultados do teste ). Possui tratamento de erros e bom desempenho. Você pode substituir com segurança a partir dereadlink -f
. A licença é CC0, para que você possa usá-la em qualquer projeto.Por favor, consulte o código mais recente. Pode algum conserto.
fonte
O Perl possui uma função de readlink (por exemplo, como copio links simbólicos no Perl? ). Isso funciona na maioria das plataformas, incluindo o OS X:
Por exemplo:
fonte
readlink
sem a-f
opção - sem recursão, sem caminho absoluto -, então você pode usarreadlink
diretamente.A resposta de @Keith Smith fornece um loop infinito.
Aqui está a minha resposta, que eu uso apenas no SunOS (o SunOS perde muitos comandos POSIX e GNU).
É um arquivo de script que você deve colocar em um dos diretórios $ PATH:
fonte
Isto é o que eu uso:
stat -f %N $your_path
fonte
Os caminhos para o readlink são diferentes entre o meu sistema e o seu. Por favor, tente especificar o caminho completo:
fonte
readlink
compatível com o gnu. É bom saber, mas não resolve o meu problema, pois preciso que meu script seja executado na máquina de outras pessoas e não posso exigir que eles instalem o fink para isso.