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
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:
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/file
elenca il numero di inode di un file. df -P /path/to/file
mostra 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 stat
comando, probabilmente può mostrare i numeri di inode e filesystem ( stat
varia 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.
fileA -ef fileB
restituisce anche 0
(esito positivo) se si fileA
tratta di un fileB
collegamento simbolico a , o viceversa, oppure entrambi si collegano allo stesso file.
[ .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
, ...
[
ed è sinonimo di test
. Ma man [
o man test
ti 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.
function is-hardlinked() {
r=yes
[ "`stat -c '%i' $1`" != "`stat -c '%i' $2`" ] && r=no
echo $r
}
stat -c %d
). E se sei su Linux (dato il tuo stat
comando), 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")"
).
function
parola chiave ingiustamente non portatile con un nome di funzione che (a causa del contenere un trattino) viola le convenzioni POSIX sui nomi consentiti?
$1
e $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.
Come suggerisce il primo poster, puoi scrivere uno script basato su qualcosa del genere su Linux:
stat -c '%i' fileA fileB fileC
stat -c %d
). E se sei su Linux (dato il tuo stat
comando), la tua shell deve [ fileA -ef fileB ]
fare tutto questo direttamente.
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 fileB
allora find
stamperà "sì" e la condizione diventa vera.
Diversamente dall'utilizzo dell'operatore di uguaglianza di file, -ef
ciò genererà un nuovo processo.