Determinando se um arquivo é um link físico ou simbólico?


51

Estou criando um script de shell que pegaria um nome de arquivo / caminho para um arquivo e determinaria se o arquivo é um link simbólico ou um link físico.

A única coisa é que eu não sei como ver se eles são um link físico. Criei 2 arquivos, um link físico e outro simbólico, para usar como arquivo de teste. Mas como eu determinaria se um arquivo é um link físico ou simbólico em um script de shell?

Além disso, como eu encontraria a partição de destino de um link simbólico? Então, digamos que eu tenha um arquivo vinculado a uma partição diferente, como eu encontraria o caminho para esse arquivo original?


16
O que você quer dizer com link físico? Todos os arquivos são links físicos.
terdon

11
@terdon ln /foo/bar/ /foo/bar2faz um hardlink enquanto ln -s /foo/bar /foo/bar2faz um link simbólico, é isso que ele quer dizer?
DisplayName

14
@DisplayName sim, mas todos os arquivos são links físicos para o seu inode. É assim que os sistemas de arquivos Linux funcionam. No seu exemplo, bar2e barsão ambos os links físicos, apenas apontando para o mesmo inode.
terdon

10
@DisplayName sim, são links físicos para outros inodes . Não há contradição aqui. Um arquivo é um link para um inode. Essa é a definição de um arquivo. No seu caso, você tem esses links em locais diferentes, mas isso não altera a estrutura de dados subjacente. Meu ponto é que tanto bare bar2são igualmente importantes. Um não é um link para o outro, ambos são links, mas apontam para o mesmo inode.
terdon

3
@ Scott não, estou dizendo que os arquivos regulares são hardlinks e que os hardlinks criados por lnnão são diferentes dos arquivos regulares.
terdon

Respostas:


42

A resposta de Jim explica como testar um link simbólico: usando testo -Lteste de.

Mas testar um "link físico" não é, estritamente falando, o que você deseja. Os links físicos funcionam devido à maneira como o Unix lida com arquivos: cada arquivo é representado por um único inode. Então, um único inode possui zero ou mais nomes ou entradas de diretório ou, tecnicamente, links físicos (o que você está chamando de "arquivo").

Felizmente, o statcomando, quando disponível, pode dizer quantos nomes um inode possui.

Então, você está procurando algo parecido com este (assumindo aqui a implementação GNU ou busybox stat):

if [ "$(stat -c %h -- "$file")" -gt 1 ]; then
    echo "File has more than one name."
fi

O -c '%h'bit informa statapenas para gerar o número de hardlinks para o inode, ou seja, o número de nomes que o arquivo possui. -gt 1depois verifica se é mais que 1.

Observe que links simbólicos, como qualquer outro arquivo, também podem ser vinculados a vários diretórios, para que você possa ter vários links físicos para um link simbólico.


ok, só para deixar claro, eu posso gerar o número de hardlinks que o arquivo possui usando o comando stat e se for maior que 1, então ele tem outro arquivo vinculado em algum lugar da partição.
k-balancim

@ k-Rocker Sim. Em seguida, ele tem um segundo nome em algum lugar da partição.
Derobert

11
No OS X ou * BSD, é stat -f %l /path/to/file. Você também pode usar gstat -c %h /path/to/filese tiver o coreutils GNU instalado sem os nomes padrão (com Homebrew no OS X).
GDP2 11/07/19

29

Um exemplo:

$ touch f1
$ ln f1 f2
$ ln f1 f3
$ ln -s f1 s1
$ ln -s f2 s2
$ ln -s ./././f3 s3
$ ln -s s3 s4
$ ln s4 s5
$ ls -li
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802345 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s1 -> f1
10802346 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s2 -> f2
10802347 lrwxrwxrwx 1 stephane stephane 8 Nov 12 19:56 s3 -> ./././f3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s4 -> s3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s5 -> s3

As entradas f1, f2e f3diretório são o mesmo arquivo (mesmo inode: 10802124, você notará que o número de links é 3). Eles são links físicos para o mesmo arquivo regular .

s4e s5também são o mesmo arquivo (10802384). Eles são do tipo link simbólico , não regulares . Eles apontam para um caminho aqui s3. Como s4e s5são entradas do mesmo diretório, esse caminho relativo s3aponta para o mesmo arquivo (aquele com inod 10802347) para ambos.

Se você fizer um ls -Ll, está pedindo para obter informações sobre o arquivo após resolver os links simbólicos:

$ ls -lLi
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s4
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s5

Você descobrirá que todos eles resolvem o mesmo arquivo (10802124).

Você pode verificar se um arquivo é um link simbólico [ -L file ]. Da mesma forma, você pode testar se um arquivo é regular [ -f file ], mas, nesse caso, a verificação é feita após a resolução dos links simbólicos.

hardlinks não são um tipo de arquivo, são apenas nomes diferentes para um arquivo (de qualquer tipo).


19

Usando os operadores -he -Ldo testcomando:

-h file 
true if file is a symbolic link

-L file 
true if file is a symbolic link

http://www.mkssoftware.com/docs/man1/test.1.asp

De acordo com esse encadeamento SO , eles têm o mesmo comportamento, mas -Lé preferido.


ok legal, mas e os links físicos? Eu verifiquei o piso, mas nada sobre links físicos. Se -L retornar falso, isso significa que é um link físico? ou apenas um arquivo regular?
k-balancim

11
Os links físicos compartilham o mesmo inode. Além disso, os links flexíveis mostram um lno início de sua ls -lsaída ... Eu acho que você pode juntar essas regras em um script, além do [[ -L file ]]teste para ver se o arquivo fornecido é flexível ou rígido .
precisa

ok, também, como eu encontraria a partição de destino do link simbólico?
k-balancim

3

Há muitas respostas corretas aqui, mas não acho que alguém realmente tenha abordado a percepção equivocada original. A pergunta original é basicamente "quando eu faço um link simbólico, é fácil identificá-lo depois. Mas não consigo descobrir como identificar um link físico". E sim, as respostas basicamente se resumem a "você não pode" e mais ou menos explicam o porquê, mas ninguém parece ter reconhecido que, na verdade, é confuso e estranho.

Se você está lendo tudo isso e descobriu o que está acontecendo, é bom; você não precisa ler meu pedacinho. Se você ainda está confuso, continue.

A resposta realmente muito curta é que um link físico não é realmente um link, não da maneira que um link simbólico é. É uma nova entrada na estrutura de diretórios que aponta para o mesmo grupo de bytes que a entrada do diretório original e, depois que você a criou, é tão 'real' e legítima quanto a primeira. Todo arquivo 'normal' na sua unidade possui pelo menos um link físico; sem isso, você não veria isso de forma algumadiretório e não conseguiria se referir a ele ou usá-lo. Portanto, se você possui um arquivo Fred.txt e vincula Wilma.txt e Barney.txt a ele, todos os três nomes (e entradas de diretório) se referem ao mesmo arquivo e todos são igualmente válidos. Não há como o sistema operacional dizer que uma das entradas foi criada quando você clicou em "salvar" no seu editor de texto e as outras foram feitas com o comando "ln".

O sistema operacional não tem que manter o controle de quantas entradas diferentes estão apontando para o mesmo arquivo, no entanto. Se você excluir o Wilma.txt, não é surpresa que você não libere espaço na sua unidade. Mas se você excluir Fred.txt (o arquivo 'original'), ainda não liberará espaço em sua unidade, porque os dados na unidade conhecidos como Fred.txt também serão Barney.txt. Somente quando você exclui todas as entradas do diretório o SO desaloca o espaço que os dados estavam ocupando.

Se o Barney.txt fosse um link simbólico, a exclusão do Fred.txt teria desalocado o espaço e o Barney.txt agora seria um link quebrado. Além disso, se você mover ou renomear um arquivo que possui um link simbólico apontando para ele, quebrará o link. Mas você pode mover ou renomear um arquivo com link físico o quanto quiser, sem interromper as outras entradas de diretório que apontam para esse arquivo / dados, porque todas elas são entradas de diretório que se referem ao mesmo bloco de dados na unidade (usando o inode # desses dados).

[Dois anos depois, e essa última parte me confundiu por um minuto, então acho que vou esclarecer. Se você digitar "mv ./Wilma.txt ../elsewhere/Betty.txt", parece que você está movendo o arquivo, mas, na verdade, não está. O que você realmente está fazendo é remover um item de linha da lista de diretórios do diretório atual, aquele que diz "o nome 'Wilma.txt' está associado aos dados que podem ser encontrados usando o inode ###### #, "e adicionando um novo item de linha à lista de diretórios ../elsewhere que diz" o nome 'Betty.txt' está associado aos dados que podem ser encontrados através do inode ####### ". É por isso que você pode 'mover' um arquivo de 2 gigabytes tão rapidamente quanto um arquivo de 2 kilobytes, desde que você os esteja movendo para outro local na mesma unidade.]

Como o sistema operacional precisa acompanhar quantas entradas de diretório diferentes estão apontando para a mesma porção de dados, é possível saber se um arquivo específico foi vinculado por hardware, mesmo que você não tenha certeza se a entrada de diretório que você está olhando é o 'original' ou não. Uma maneira é o comando "ls", especificamente "ls -l" (é um L minúsculo após o traço)

Para emprestar um exemplo anterior ....

 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1

A primeira letra é um traço, por isso não é um diretório ou outra coisa exótica, é um arquivo comum 'regular'. Mas se fosse realmente comum, esse número após a parte rwx-ish seria "1", como em "há uma entrada de diretório apontando para esse bloco de dados". Mas isso faz parte de uma demonstração de links físicos, então diz "3".

Observe que isso pode levar a um comportamento estranho e misterioso (se você não tiver envolvido a cabeça em links físicos, isso é). Se você abrir o Fred.txt no seu editor de texto e fizer algumas alterações, verá as mesmas alterações no Wilma.txt e no Barney.txt? Talvez. Provavelmente. Se o seu editor de texto salvar as alterações, abrindo o arquivo original e escrevendo as alterações, sim, todos os três nomes ainda estarão apontando para o mesmo texto (recém-alterado). Mas se o seu editor de texto cria um novo arquivo (Fred-new-temp.txt), grava a versão alterada nele, exclui Fred.txt e renomeia Fred-new-temp.txt para Fred.txt, Wilma e Barney irão ainda está apontando para a versão original, não para a nova versão alterada. Se você não entender os links físicos, isso pode deixá-lo um pouco louco. :) [Ok, na verdade eu não conheço pessoalmente nenhumeditores de texto que executariam a coisa de novo arquivo / renomeação, mas eu conheço muitos outros programas que fazem exatamente isso, portanto, fique alerta.]

Uma observação final: uma das coisas que o 'fsck' (verificação do sistema de arquivos) verifica é se há blocos de dados em sua unidade que de alguma forma não são mais referenciados por nenhuma entrada de diretório. Às vezes, algo dá errado, e a única entrada de diretório que aponta para um inode é excluída, mas o espaço da unidade em si não é marcado como "disponível". Portanto, uma das tarefas do fsck é combinar todo o espaço alocado com todas as entradas do diretório para garantir que não haja arquivos não referenciados. Se encontrar algum, ele cria novas entradas de diretório e as coloca em "perdido + encontrado".


Imaginando, quais são esses "outros programas que fazem exatamente isso"?
Php3

@phk Não sei o que ele está pensando especificamente, mas essa é uma abordagem bastante comum para executar ações que podem levar muito tempo e que o deixarão em um estado incerto se falharem. Por exemplo, se você tentar fazer o download de um servidor remoto e souber que há uma chance de o tempo limite do servidor expirar, uma abordagem seria fazer o download de todo o conteúdo em um arquivo temporário. Dessa forma, se algo der errado com o download, você ainda terá o arquivo original.
Cwallenpoole

O único programa que eu sei com certeza é o FreeHand, porque se / quando ele falha durante o salvamento, há um arquivo temporário deixado para trás, em vez de um arquivo original mutilado. Mas já vi outros programas fazerem isso também; Só não posso dar exemplos específicos neste momento.
Snarke

2

você pode usar readlink FILE; echo $?. Isso retorna 1 quando é um link físico e 0 quando é um link simbólico.

Na página do manual: "Quando chamado como readlink, apenas o destino do link simbólico é impresso. Se o argumento fornecido não for um link simbólico, o readlink não imprimirá nada e sairá com um erro".

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.