Due file sono hardlinked?


27

Come posso sapere se due file sono hard-linkati dalla riga di comando? ad esempio qualcosa collega questo:

$ ls
fileA fileB fileC

$ is-hardlinked fileA fileB
yes

$ is-hardlinked fileA fileC
no

Risposte:


37

Sulla maggior parte dei filesystem¹, un file è determinato in modo univoco dal suo numero di inode , quindi tutto ciò che devi controllare è se i due file hanno lo stesso numero di inode e si trovano sullo stesso filesystem.

Ash, ksh, bash e zsh hanno un costrutto che fa il controllo per te: l'operatore di uguaglianza dei file -ef.

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

Per i casi più avanzati, ls -i /path/to/fileelenca il numero di inode di un file. df -P /path/to/filemostra su quale file system si trova il file (se due file si trovano nella stessa directory, si trovano nello stesso filesystem). Se il tuo sistema ha il statcomando, probabilmente può mostrare i numeri di inode e filesystem ( statvaria da sistema a sistema, controlla la tua documentazione). Se vuoi dare una rapida occhiata ai collegamenti reali all'interno di una directory, prova ls -i | sort(possibilmente reindirizzato a awk ).

¹ Tutti i filesystem unix nativi e pochi altri come NTFS, ma forse non casi esotici come CramFS.


E sicuramente non su nulla basato su FAT, dove verrebbe rilevato come un file "cross-linked".
Ignacio Vazquez-Abrams,

4
Si noti che fileA -ef fileBrestituisce anche 0(esito positivo) se si fileAtratta di un fileBcollegamento simbolico a , o viceversa, oppure entrambi si collegano allo stesso file.
Janmoesen,

come si esegue effettivamente il comando suggerito? Ho provato [.bashrc -ef .bash / .bashrc] e varianti di questo ma non ha funzionato.
Charlie Parker,

@CharlieParker [ .bashrc -ef .bash/.bashrc ]è corretto. Senza contesto, ovviamente, non ho idea del perché "non ha funzionato davvero" - potresti confrontare i file sbagliati, non potresti controllare il risultato correttamente, potresti usare una shell senza -ef, ...
Gilles 'SO- smetti di essere malvagio' il

2
@CharlieParker Il comando è in realtà [ed è sinonimo di test. Ma man [o man testti darà la pagina man del comando esterno, mentre quasi tutte le shell là fuori hanno un comando integrato con opzioni leggermente diverse, quindi devi cercare questa nel manuale della tua shell.
Gilles 'SO- smetti di essere malvagio' il

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

6
Nota che questo può essere un falso positivo se i due file si trovano su filesystem diversi ma hanno lo stesso inode. È necessario testare anche il numero del dispositivo ( stat -c %d). E se sei su Linux (dato il tuo statcomando), la tua shell deve [ fileA -ef fileB ]fare tutto questo direttamente. Inoltre, il tuo comando si interrompe gratuitamente con i nomi dei file contenenti spazi bianchi o \[?*, o inizia con -: metti sempre doppie virgolette attorno al comando susbtitutions ( "$(stat -c %i -- "$1")").
Gilles 'SO- smetti di essere malvagio' il

1
Perché dovresti usare un mucchio di costrutti ingombranti ma portatili, e quindi la functionparola chiave ingiustamente non portatile con un nome di funzione che (a causa del contenere un trattino) viola le convenzioni POSIX sui nomi consentiti?
Charles Duffy,

Hai dimenticato di citare il tuo $1e $2. È inoltre possibile utilizzare la $()sintassi anziché i backtick poiché le parentesi indicano chiaramente dove inizia il comando e dove termina e l'annidamento è più semplice.
josch,

3

Come suggerisce il primo poster, puoi scrivere uno script basato su qualcosa del genere su Linux:

stat -c '%i' fileA fileB fileC

4
Questo non è abbastanza: otterrai lo stesso numero per i due file se si trovano su filesystem diversi ma hanno lo stesso inode. È necessario testare anche il numero del dispositivo ( stat -c %d). E se sei su Linux (dato il tuo statcomando), la tua shell deve [ fileA -ef fileB ]fare tutto questo direttamente.
Gilles 'SO- smetti di essere malvagio' il

0

Con GNU find(1)versione 4.2.11 o successiva puoi anche usare questo:

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

Se fileAè lo stesso file di fileBallora findstamperà "sì" e la condizione diventa vera.

Diversamente dall'utilizzo dell'operatore di uguaglianza di file, -efciò genererà un nuovo processo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.