eu corro
ln /a/A /b/B
Gostaria de ver na pasta a
onde o arquivo A aponta para ls
.
linux
filesystems
hardlink
Léo Léopold Hertz 준영
fonte
fonte
link(2)
chamada do sistema, não há sentido em qual é o original e o que é o link. É por isso que, como as respostas apontam, a única maneira de encontrar todos os links éfind / -samefile /a/A
. Como uma entrada de diretório para um inode não "conhece" outras entradas de diretório para o mesmo inode. Tudo o que eles fazem é refcount o inode para que ele possa ser excluído quando o sobrenome forunlink(2)ed
. (Esta é a "contagem de links" nals
saída).Respostas:
Você pode encontrar o número do inode para seu arquivo com
e
mostra a contagem de referências (número de hardlinks para um inode específico)
depois de encontrar o número do inode, você pode procurar todos os arquivos com o mesmo inode:
mostrará os nomes dos arquivos para o inode NUM no diretório atual (.)
fonte
Não há realmente uma resposta bem definida para sua pergunta. Ao contrário dos links simbólicos, os links físicos são indistinguíveis do "arquivo original".
As entradas do diretório consistem em um nome de arquivo e um ponteiro para um inode. O inode, por sua vez, contém os metadados do arquivo e (indicadores para) o conteúdo real do arquivo). Criar um link físico cria outro nome de arquivo + referência para o mesmo inode. Essas referências são unidirecionais (pelo menos em sistemas de arquivos típicos) - o inode mantém apenas uma contagem de referência. Não há uma maneira intrínseca de descobrir qual é o nome do arquivo "original".
A propósito, é por isso que a chamada do sistema para "excluir" um arquivo é chamada
unlink
. Apenas remove um hardlink. O inode e os dados anexados serão excluídos apenas se a contagem de referência do inode cair para 0.A única maneira de encontrar as outras referências a um determinado inode é pesquisar exaustivamente no sistema de arquivos, verificando quais arquivos se referem ao inode em questão. Você pode usar 'test A -ef B' no shell para executar esta verificação.
fonte
O UNIX possui links físicos e simbólicos (criados com
"ln"
e"ln -s"
respectivamente). Links simbólicos são simplesmente um arquivo que contém o caminho real para outro arquivo e pode atravessar sistemas de arquivos.Os hard links existem desde os primeiros dias do UNIX (que eu me lembro de qualquer maneira, e isso já faz um bom tempo). São duas entradas de diretório que referenciam exatamente os mesmos dados subjacentes. Os dados em um arquivo são especificados por seus
inode
. Cada arquivo em um sistema de arquivos aponta para um inode, mas não é necessário que cada arquivo aponte para um inode exclusivo - é daí que os links físicos vêm.Como os inodes são exclusivos apenas para um determinado sistema de arquivos, há uma limitação de que os links físicos devem estar no mesmo sistema de arquivos (diferente dos links simbólicos). Observe que, diferentemente dos links simbólicos, não há arquivo privilegiado - todos são iguais. A área de dados será liberada somente quando todos os arquivos que usam esse inode forem excluídos (e todos os processos também serão fechados, mas esse é um problema diferente).
Você pode usar o
"ls -i"
comando para obter o inode de um arquivo específico. Você pode usar o"find <filesystemroot> -inum <inode>"
comando para encontrar todos os arquivos no sistema de arquivos com o inode fornecido.Aqui está um script que faz exatamente isso. Você o invoca com:
e encontrará todos os arquivos nesse sistema de arquivos que são links físicos para esse arquivo:
Aqui está o script.
fonte
. ./findhardlinks.bash
estar no Zsh do OS X. Minha janela atual na tela se fecha.INUM=$(stat -c %i $1)
. TambémNUM_LINKS=$(stat -c %h $1)
. Vejaman stat
para obter mais variáveis de formato que você pode usar.A primeira coluna representará permissões. A segunda coluna será o número de subitens (para diretórios) ou o número de caminhos para os mesmos dados (links físicos, incluindo o arquivo original) para o arquivo. Por exemplo:
fonte
inode
que, por sua vez, aponta para o conteúdo do disco.Que tal o seguinte, mais simples? (Os últimos podem substituir os scripts longos acima!)
Se você possui um arquivo específico
<THEFILENAME>
e deseja conhecer todos os seus hardlinks espalhados pelo diretório<TARGETDIR>
, (que pode até ser todo o sistema de arquivos indicado por/
)Estendendo a lógica, se você quiser conhecer todos os arquivos nos
<SOURCEDIR>
vários links físicos espalhados<TARGETDIR>
:fonte
-type f
porque o arquivo também pode ser um diretório..
e..
nos diretórios são hardlinks. Você pode dizer quantos subdiretórios estão em um diretório a partir da contagem de links de.
. Isso é discutível de qualquer maneira, já quefind -samefile .
ainda não imprimirá nenhumasubdir/..
saída.find
(pelo menos a versão GNU) parece estar codificado para ignorar..
, mesmo com-noleaf
.O(n^2)
executadafind
uma vez para cada membro de um conjunto de arquivos vinculados.find ... -printf '%16i %p\n' | sort -n | uniq -w 16 --all-repeated=separate
iria funcionar, (16 não é grande o suficiente para uma representação decimal de 2 ^ 63-1, então quando seu sistema de arquivos XFS é grande o suficiente para ter números de inode que a alta, atente)Existem muitas respostas com scripts para encontrar todos os hardlinks em um sistema de arquivos. A maioria deles faz coisas tolas, como a execução de localizar, para verificar todo o sistema de arquivos em
-samefile
busca de CADA arquivo vinculado à multiplicação. Isso é loucura; tudo o que você precisa é escolher o número do inode e imprimir duplicatas.Com apenas uma passagem pelo sistema de arquivos para encontrar e agrupar todos os conjuntos de arquivos vinculados
Isso é muito mais rápido que as outras respostas para encontrar vários conjuntos de arquivos com links físicos.
find /foo -samefile /bar
é excelente para apenas um arquivo.-xdev
: limite para um sistema de arquivos. Não é estritamente necessário, pois também imprimimos o FS-id para uniq em! -type d
diretórios de rejeição: as entradas.
e..
significam que elas estão sempre vinculadas.-links +1
: contagem de links estritamente> 1
-printf ...
imprima o ID do FS, o número do inode e o caminho. (Com preenchimento para larguras de colunas fixas que podemos saberuniq
.)sort -n | uniq ...
classificação numérica e unificar nas 42 primeiras colunas, separando grupos com uma linha em brancoUsar
! -type d -links +1
significa que a entrada da classificação é apenas tão grande quanto a saída final do uniq, portanto não estamos fazendo uma grande quantidade de classificação de string. A menos que você o execute em um subdiretório que contenha apenas um de um conjunto de links físicos. De qualquer forma, isso consumirá muito menos tempo de CPU ao atravessar o sistema de arquivos do que qualquer outra solução publicada.saída de amostra:
TODO?: Desmarque a saída com
awk
oucut
.uniq
tem suporte de seleção de campo muito limitado, por isso, preencha a saída de localização e uso a largura fixa. 20chars é grande o suficiente para o número máximo possível de inode ou dispositivo (2 ^ 64-1 = 18446744073709551615). O XFS escolhe números de inodes com base em onde eles estão alocados no disco, e não contíguamente de 0, para que sistemas de arquivos XFS grandes possam ter números de inode> 32 bits, mesmo que não tenham bilhões de arquivos. Outros sistemas de arquivos podem ter números de inode de 20 dígitos, mesmo que não sejam gigantescos.TODO: classifica grupos de duplicatas por caminho. Classificá-los por ponto de montagem, em seguida, o número do inode combina tudo, se você tiver alguns subdiretórios diferentes que possuem muitos hardlinks. (ou seja, grupos de grupos duplos andam juntos, mas a saída os mistura).
Uma final
sort -k 3
classificaria as linhas separadamente, não grupos de linhas como um único registro. O pré-processamento de algo para transformar um par de novas linhas em um byte NUL, e o uso do GNUsort --zero-terminated -k 3
pode ajudar.tr
só opera com caracteres únicos, mas não com padrões 2-> 1 ou 1-> 2.perl
faria isso (ou apenas analisaria e classificaria dentro de perl ou awk).sed
também pode funcionar.fonte
%D
é o identificador de sistema de arquivos (que é único para a inicialização atual, enquanto há sistemas de arquivos sãoumount
ed), de modo que se segue é ainda mais genérica:find directories.. -xdev ! -type d -links +1 -printf '%20i %20D %p\n' | sort -n | uniq -w 42 --all-repeated=separate
. Isso funciona desde que nenhum diretório contenha outro diretório no nível do sistema de arquivos, mas também analisa tudo o que pode ser vinculado por hardware (como dispositivos ou softlinks - sim, os softlinks podem ter uma contagem de links maior que 1). Note quedev_t
eino_t
tem 64 bits hoje. Isso provavelmente será válido enquanto tivermos sistemas de 64 bits.! -type d
, em vez de-type f
. Eu até tenho alguns links simbólicos vinculados no meu sistema de arquivos ao organizar algumas coleções de arquivos. Atualizei a minha resposta com a sua versão melhorada (mas eu coloquei o fs-id primeiro, então a ordem de classificação, pelo menos, grupos de sistema de arquivos.)Isso é um comentário à própria resposta e roteiro de Torocoro-Macho, mas obviamente não cabe na caixa de comentários.
Reescreva seu script com maneiras mais simples de encontrar as informações e, portanto, muito menos invocações de processos.
Tentei mantê-lo o mais semelhante possível ao seu para facilitar a comparação.
Comentários sobre este script e o seu
Deve-se sempre evitar a
$IFS
magia se uma glob é suficiente, uma vez que é desnecessariamente complicada, e os nomes dos arquivos podem realmente conter novas linhas (mas, na prática, principalmente a primeira razão).Você deve evitar a análise manual
ls
e essa saída, tanto quanto possível, pois mais cedo ou mais tarde você será mordido. Por exemplo: na sua primeiraawk
linha, você falha em todos os nomes de arquivos que contêm espaços.printf
muitas vezes salvará problemas no final, pois é muito robusto com a%s
sintaxe. Também oferece controle total sobre a saída e é consistente em todos os sistemas, ao contrárioecho
.stat
pode economizar muita lógica nesse caso.GNU find
é poderoso.Suas invocações
head
etail
poderiam ter sido tratadas diretamenteawk
com, por exemplo, oexit
comando e / ou a seleção naNR
variável. Isso salvaria as invocações do processo, que quase sempre melhoram o desempenho severamente em scripts de trabalho árduo.Seus
egrep
s poderiam muito bem ser justosgrep
.fonte
find ... -xdev -type f -links +1 -printf '%16i %p\n' | sort -n | uniq -w 16 --all-repeated=separate
. Isso é MUITO mais rápido, pois ele atravessa o fs apenas uma vez. Para vários FSes de uma só vez, você precisa prefixar os números dos inodes com um ID de FS. Talvez comfind -exec stat... -printf ...
Baseado no
findhardlinks
script (renomeado parahard-links
), é isso que refatorei e fiz funcionar.Resultado:
fonte
Uma solução GUI fica muito próxima da sua pergunta:
Você não pode listar os arquivos vinculados reais de "ls" porque, como os comentaristas anteriores apontaram, os "nomes" do arquivo são meros aliases para os mesmos dados. No entanto, na verdade, existe uma ferramenta GUI que se aproxima muito do que você deseja, que é exibir uma lista de caminhos de nomes de arquivos que apontam para os mesmos dados (como hardlinks) no linux, chamada FSLint. A opção desejada está em "Confrontos de nomes" -> desmarque "caixa de seleção $ PATH" em Pesquisa (XX) -> e selecione "Aliases" na caixa suspensa após "para ..." na parte superior central.
O FSLint está muito mal documentado, mas descobri que a árvore de diretórios limitada em "Caminho de pesquisa" está marcada com a caixa de seleção selecionada para "Recurso?" e as opções acima mencionadas, uma lista de dados vinculados com caminhos e nomes que "apontam" para os mesmos dados são produzidos após a pesquisa do programa.
fonte
Você pode configurar
ls
para destacar os hardlinks usando um 'alias', mas, como afirmado anteriormente, não há como mostrar a 'fonte' do hardlink, e é por isso que anexo.hardlink
para ajudá-lo.Adicione o seguinte em algum lugar do seu
.bashrc
fonte