encontre todos os links (hard e links simbólicos, e qualquer combinação deles) levando a um arquivo / dir [duplicado]

1

Eu leio "a maioria" das perguntas propostas, mas acredito que todas elas perdem a complexidade da resposta certa.

Eu quero, usando apenas comandos "básicos" (para portabilidade máxima) (isto é, algo que funcionaria no AIX / Linux / etc., não apenas algo usando um nicety recente ^^), para encontrar all os arquivos (links simbólicos, hardlinks e combinações dos mesmos) apontando para um arquivo / diretório específico.

Tenha cuidado para não se apressar em responder find / -ls | grep .... : ele perderá muitos casos. Veja meus links abaixo, misturando hardlinks, links simbólicos, caminhos relativos e absolutos (e também reproduza com links simbólicos "././././." Possibilidades)

ou seja

  • hardlinks e links simbólicos podem ser "aninhados", ad-inifinitum ...
  • alguns links simbólicos podem estar com o caminho completo, outros com um caminho relativo,
  • esses caminhos (relativos ou absolutos) podem ser muito complexos (ex: /tmp/././../etc/file)
  • um link simbólico pode levar a um arquivo, que é um link para outro, que é um link simbólico para um terceiro, que acaba [depois de mais algumas iterações] para o destino final ...

No final, eu "apenas" preciso descobrir uma maneira de saber qual é o "destino final" de qualquer arquivo / link (ou seja, qual inode será acessado no final? ). Mas é muito difícil (a menos que alguma função mágica me diga "o destino final é: ...". É disso que eu preciso!)

Eu achei que poderia simplesmente usar as opções '-H' ou '-L', mas (provavelmente sou burro ...) não funcionou ... ainda.

Qualquer informação é bem-vinda (mas, por favor, use find / ls / etc, não algum "utilitário legal disponível apenas no linux")

Tente criar alguns links diferentes para o diretório "/ tmp / A" e encontre uma maneira de encontrar e listar todos:

mkdir /tmp/A    /tmp/B
ln -s /tmp/A/   /tmp/B/D  #absolute symlink, with a training "/"
ln -s ../A      /tmp/B/E     #relative symlink
ln -s /tmp/A/.  /home/F  #absolute symlink, with a trailing "/."
ln -s ../tmp/A/./.  /var/L  #let's get craaaaaaazy! symlinks are "fun"...
ln    /tmp/B/D  /etc/G    #Hard-link to the symlink file /tmp/B/D, which itself symlink to /tmp/A/ witch ends up being the same as "/tmp/A" in most cases.
ln    /etc/G    /etc/G2   #and a duplicate of the previous one, just to be sure [so /etc/G, /etc/G2, and /tmp/B/D have same inode, but it's a different inode from the final destination... :(
ln -s etc/G /thatsenough   #symlink again, for further chaining

e depois algumas tentativas:

find -H / -ls   # show inodes of the links and symlinks, not of the "final" directory
find -L / -ls   # same thing (I do try that on an OLD AIX ...)
find -H / -inum 123456 -ls  #if /tmp/A/. has inode 123456. This lists *only* hardlinks to /tmp/A, ie will only print a subset (and /tmp/A have to be a file in that case)

Eu esperava ver o inode final (123456) na frente de todos os caminhos, em uma dessas invocações (eu também adicionei '-follow' a ambos), mas eu sempre vejo os inodes dos links, não do "destino final" (ou seja, / tmp / A)

O que eu poderia usar para descobrir o "inodo final" que acabo acessando? [o sistema operacional gerencia isso, mas pode um comando "simples" dizer antecipadamente "através do esse arquivo, você abrirá aquele inode final!"]

    
por Olivier Dulac 07.11.2013 / 19:20

4 respostas

1

ls tem uma opção -L que irá efetivamente perseguir links simbólicos e mostrar os perms, owner, inode, etc. do objeto final. [Ele faz isso fazendo stat(target) em vez de lstat(target) ]. Para obter melhores resultados, execute como root ou como alguém que tenha acesso de leitura a sistemas de arquivos montados relevantes.

Portanto, no seu caso, tente o seguinte:

find / -exec ls -iLd {} | grep inodenum

[copiado do meu comentário, por solicitação do OP.]

    
por 08.11.2013 / 21:34
2

A questão não é respondível de maneira uniforme. Por exemplo, encadeando apenas alguns links simbólicos em uma árvore, posso criar infinitamente muitos caminhos possíveis que são resolvidos para o mesmo inode.

O seu desejo de portabilidade completa também é improvável que tenha sucesso. Por exemplo, até mesmo "encontrar" difere na natureza entre GNU, BSD, POSIX e outras variantes (e, é claro, entre versões dessas variantes).

Mas o que você quer pode ser algo parecido com find / -samefile /absolute/path/to/file .

Isso está disponível no GNU find > = 4.2.11.

    
por 07.11.2013 / 22:56
0

update : A resposta de Mark Plottnick (sob minha pergunta) foi muito mais simples e funciona para arquivos & diretórios, e dá o inode do destino final após qualquer combinação de links entre eles!
Era o que eu estava procurando [a menos que eu tenha esquecido casos especiais no meu diretório de teste]. Fico feliz que a solução final seja tão elegante e portátil! Mark, por favor, poste-o para que eu possa lhe dar a marca de verificação ^^

Eu deixei minha própria solução abaixo, que agora parece muito bobo ^^

===

Eu encontrei uma solução incrivelmente fácil quando o arquivo de destino é um diretório! Basta adicionar um "/". depois do nome, e você terá o diretório inode do destino final! E você ainda imprime o caminho de origem!

find / -print | xargs -n 1 ls -ild '{}'/. 2>/dev/null | grep inodeyouwant

nota: é muito pesado em "tentar fazer isso em um arquivo sem saber se é um link simbólico ou hardlink", então eu atualizarei com um que apenas procure links físicos + links simbólicos.

Mas agora eu preciso descobrir uma maneira de fazer isso para o arquivo "não-guia-para-um-diretório-no-final" [s] (isto é, links / links simbólicos / cadeia-de-aqueles que no ponto final para algo que não é um diretório) (mais uma vez, sem modificar esse destino final!)

Vou atualizar quando encontrar uma maneira legal para isso

    
por 08.11.2013 / 10:26
0

Com o GNU find :

find -L . \( ! -xtype l -o -prune \) -samefile /path/to/the/file -print

Informaria os diferentes caminhos canônicos que levam ao mesmo arquivo que /path/to/the/file

com zsh :

printf '%s\n' **/*(De:'[[ $REPLY -ef /path/to/the/file ]]')

O [ file -ef other-file ] ainda não é POSIX, mas é amplamente suportado e há conversa de incluí-lo na próxima versão da especificação .

find . -exec sh -c '
  for file do
    [ "$file" -ef /path/to/the/file ] && printf "%s\n" "$file"
  done' sh {} +

Deve funcionar contanto que sh seja baseado em AT & T ksh , pdksh , bash , zsh , ash ou yash pelo menos (e eu não sei qualquer implementação POSIX sh que não seja baseada em nenhuma delas).

    
por 07.10.2015 / 14:03