Come posso verificare se si /my/dir
trova sulla stessa partizione di /
?
Questo è per l'integrazione all'interno di uno script. I supporti di collegamento devono essere gestiti correttamente. Le soluzioni compatibili POSIX sono benvenute.
Come posso verificare se si /my/dir
trova sulla stessa partizione di /
?
Questo è per l'integrazione all'interno di uno script. I supporti di collegamento devono essere gestiti correttamente. Le soluzioni compatibili POSIX sono benvenute.
Risposte:
Puoi verificarlo con stat:
$ stat -c '%d %m' /proc/sys/
3 /proc
Ti mostra il numero del dispositivo e dove è stata montata la tua directory.
stat
comando shell non è POSIX ...
Il comando seguente fornisce un nome univoco per il punto di montaggio contenente il file $file
:
df -P -- "$file" | awk 'NR==2 {print $1}'
Funziona su qualsiasi sistema POSIX . L' -P
opzione impone un formato prevedibile; il primo campo della seconda riga è il "nome del file system". Pertanto, per controllare due file si trovano nello stesso punto di montaggio:
if [ "$(df -P -- "$file1" | awk 'NR==2 {print $1}')" = \
"$(df -P -- "$file2" | awk 'NR==2 {print $1}')" ]; then
echo "$file1 and $file2 are on the same filesystem" ; fi
Oppure, per salvare un paio di invocazioni di processo:
if df -P -- "$file1" "$file2" |
awk 'NR!=1 {dev[NR] = $1} END {exit(dev[2] != dev[3])}'; then
echo "$file1 and $file2 are on the same filesystem" ; fi
Alcuni sistemi operativi possono avere spazi nei nomi dei volumi. In df
questo caso non esiste un modo completamente affidabile per analizzare l' output.
Sotto il cofano, puoi identificare il filesystem contenente un file dal st_dev
campo restituito da stat
. Non esiste un modo portatile per farlo da uno script di shell. Alcuni sistemi hanno stat
un'utilità, ma la sua sintassi varia:
stat
segnala il st_dev
campo quando invocato come stat -c %D -- "$file"
.stat
compatibile con i coreutils GNU. Altri hanno stat
senza l' %c
opzione; puoi usarlo, stat -t -- "$file" | awk '{print $8}'
ma funziona solo se il nome del file non contiene spazi bianchi o se fa stat -t -- "$file" | awk 'END {print $(NF-8)}'
fronte a nomi di file arbitrari ma non con future aggiunte di campi stat
all'output.stat
un'utilità diversa che richiede stat -f %d -- "$file"
.stat
utilità.Se Perl è disponibile, è possibile utilizzare
perl -e 'print ((stat($ARGV[0]))[0])' -- "$file"
e per fare il confronto:
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- "$file1" "$file2"
Si noti che ci sono alcuni casi angolari in cui il risultato desiderato non è chiaro. Ad esempio, con supporti bind di Linux, dopo mount --bind /foo /bar
, /foo
e /bar
sono considerati lo stesso file system. È sempre possibile che i due file si trovino effettivamente sullo stesso dispositivo, ma non lo saprai mai: ad esempio, se i file si trovano su due diversi montaggi di rete, il client non ha modo di sapere se il server sta esportando file system diversi.
Se i file sono directory e puoi scriverli, un altro metodo è quello di creare un file temporaneo e tentare di creare un collegamento reale. Questo riporta un risultato negativo su tutti i mount bind di Linux.
tmp1=$(TMPDIR=$dir1 mktemp)
tmp2=$(TMPDIR=$dir2 mktemp)
if ln -f -- "$tmp1" "$tmp2"; then
echo "$dir1 and $dir2 are on the same filesystem, which supports hard links"
fi
rm -f "$tmp1" "$tmp2"
df
non sempre fornisce il nome del dispositivo, ma a volte un link simbolico ad esso non /dev/disk/by-uuid/ca09b761-ae1b-450f-8a46-583327b48fb4
rende df
affidabile. L'unica opzione affidabile finora è l'utilizzo di una stat
soluzione basata su.
df
riportato per il dispositivo, è coerente tra le due invocazioni, quindi va bene per un confronto.
df
report /dev/sda6
e /dev/disk/by-uuid/ca09b...
, entrambi riferiti allo stesso dispositivo, ma punti di mount diversi. Il test di confronto delle stringhe ovviamente fallisce quando si prova con file da ciascun punto di montaggio.
mount /dev/sda6 /mnt1
seguito da mount /dev/sda6 /mnt2
opere come un fascino. cat /proc/mounts
va bene con esso. Tuttavia, è solo da Wheezy che /dev/disk/by-uuid/ca09b...
viene mostrato df
come dispositivo per il filesystem di root. Ulteriori tentativi di montarlo usando questo simlink o la UUID=ca09b...
sintassi del mount non finiscono per mostrare nient'altro che /dev/sda6
in df
(non so come riprodurre ciò che ha fatto durante il processo di avvio, ma non è questo il problema).
test $(df -P $path1 $path2 | awk '{if (NR!=1) {print $6}}' | uniq | wc -l) -eq 1
Funziona con qualsiasi numero di percorsi.
$6
), non il nome del dispositivo ( $1
), quindi non dovrebbe essere un problema.
La migliore soluzione infallibile disponibile in POSIX è il confronto degli ID dispositivo dei file forniti dalla funzione stat (2) .
Perl ha una funzione statistica simile a quella indicata da Gilles :
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- file1 file2
ma il "modo POSIX" è usare un programma C come:
./checksamedev file1 file2
quale codice sorgente è il seguente:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
struct stat s1, s2;
if( argc==3 && lstat(argv[1], &s1)==0 && lstat(argv[2], &s2)==0 )
return !(s1.st_dev == s2.st_dev);
return 2;
}
Se gli ID dispositivo di entrambi i file sono uguali, sono ospitati sullo stesso filesystem, nel qual caso i comandi sopra restituiscono 0 (un altro valore altrimenti). Verificare con echo $?
.
Funziona bene con i montaggi di bind, ma probabilmente non con i montaggi di rete.