Dois arquivos estão vinculados?


27

Como posso saber se dois arquivos estão vinculados na linha de comando? por exemplo, algo vincula isso:

$ ls
fileA fileB fileC

$ is-hardlinked fileA fileB
yes

$ is-hardlinked fileA fileC
no

Respostas:


37

Na maioria dos sistemas de arquivos¹, um arquivo é determinado exclusivamente por seu número de inode ; portanto, tudo que você precisa verificar é se os dois arquivos têm o mesmo número de inode e se estão no mesmo sistema de arquivos.

Ash, ksh, bash e zsh têm uma construção que faz a verificação para você: o operador de igualdade de arquivos -ef.

[ fileA -ef fileB ] && ! [ fileA -ef fileC ]

Para casos mais avançados, ls -i /path/to/filelista o número do inode de um arquivo. df -P /path/to/filemostra em que sistema de arquivos o arquivo está (se dois arquivos estiverem no mesmo diretório, eles estão no mesmo sistema de arquivos). Se o seu sistema possuir o statcomando, provavelmente poderá mostrar os números do inode e do sistema de arquivos ( statvaria de sistema para sistema, verifique sua documentação). Se você quiser ver rapidamente os links físicos dentro de um diretório, tente ls -i | sort(possivelmente direcionado para o awk ).

¹ Todos os sistemas de arquivos unix nativos e alguns outros como NTFS, mas possivelmente não casos exóticos como o CramFS.


E definitivamente não em nada baseado em FAT, onde seria detectado como um arquivo "reticulado".
— Ignacio Vazquez-Abrams,

4
Observe que fileA -ef fileBtambém retorna 0(êxito) se fileAfor um link simbólico para fileB, ou vice-versa, ou ambos os links para o mesmo arquivo.
— janmoesen

como você realmente executa o comando sugerido? Eu tentei [.bashrc -ef .bash / .bashrc] e variações disso, mas realmente não funcionou.
— Charlie Parker

@CharlieParker [ .bashrc -ef .bash/.bashrc ]está correto. Sem contexto, é claro, não tenho idéia do por que "realmente não funcionou" - você pode comparar os arquivos errados, não verificar o resultado corretamente, usar um shell sem -ef, ...
— Gilles 'SO- pare de ser mau'

2
@CharlieParker O comando é realmente [e é sinônimo de test. Mas man [ou man testfornecerá a página de manual do comando externo, enquanto quase todos os shell existentes têm um comando interno com opções ligeiramente diferentes, portanto, você deve procurar este no manual do shell.
— Gilles 'SO- stop be evil'

4
function is-hardlinked() {
    r=yes
    [ "`stat -c '%i' $1`" != "`stat -c '%i' $2`" ] && r=no
    echo $r
}

6
Observe que isso pode ser um falso positivo se os dois arquivos estiverem em sistemas de arquivos diferentes, mas tiverem o mesmo inode. Você também precisa testar o número do dispositivo ( stat -c %d). E se você estiver no Linux (dado seu statcomando), seu shell deve [ fileA -ef fileB ]fazer tudo isso diretamente. Além disso, seu comando quebra gratuitamente com nomes de arquivos que contenham espaços em branco ou \[?*, ou começa com -: sempre coloque aspas duplas em torno do comando susbtitutions ( "$(stat -c %i -- "$1")").
— Gilles 'SO- stop be evil'

11
Por que você usaria um monte de construções pesadas, mas portáteis e, em seguida, a functionpalavra - chave extremamente portátil, com um nome de função que (por conter um traço) viola as convenções POSIX em nomes permitidos?
— Charles Duffy

Você esqueceu de citar seu $1e $2. Você também pode usar a $()sintaxe em vez de backticks, porque os colchetes deixam claro onde o comando começa e onde termina e o aninhamento é mais simples.
— Josch

3

Como o primeiro pôster sugere, você pode escrever um script baseado em algo como isto no Linux:

stat -c '%i' fileA fileB fileC

4
Isso não é suficiente: você obterá o mesmo número para os dois arquivos se estiver em sistemas de arquivos diferentes, mas tiver o mesmo inode. Você também precisa testar o número do dispositivo ( stat -c %d). E se você estiver no Linux (dado seu statcomando), seu shell deve [ fileA -ef fileB ]fazer tudo isso diretamente.
— Gilles 'SO- stop be evil'

0

Com o GNU find(1)versão 4.2.11 ou mais recente, você também pode usar este:

if [ "yes" = "$(find fileA -samefile fileB -exec echo yes \;)" ]; then
    echo yes
else
    echo no
fi

Se fileAfor o mesmo arquivo fileB, findele imprimirá "yes" e a condição se tornará verdadeira.

Ao contrário do uso do operador de igualdade de arquivos, -efisso gerará um novo processo.

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.