Quest'altra risposta menziona stat
. Miglioriamo l'approccio:
a="$(stat --format=%d:%i -- "$(pwd)/expected-subdir/")" || printf "Error A\n" >&2
b="$(stat --format=%d:%i -- "$VARIABLE_PATH/expected-subdir/")" || printf "Error B\n" >&2
[ "$a" = "$b" ] || printf "Not the same path.\n" >&2
Gli appunti:
- Stiamo utilizzando
stat --format=
, quindi non sono necessari ulteriori analisi.
%d
è il numero del dispositivo, %i
è il numero dell'inode. Quest'ultimo da solo non è sufficiente perché due oggetti su dispositivi diversi (filesystem) possono avere lo stesso numero di inode.
- La shell è abbastanza intelligente da gestire separatamente le virgolette dentro e fuori
$( )
.
printf
-s sono solo matrici per la gestione degli errori. Nella vera sceneggiatura probabilmente vorresti qualcosa del genere
[ "$a" = "$b" ] || { printf "Not the same path.\n" >&2; exit 2; }
Il percorso inesistente causerà stat
un errore.
- Le barre finali sono importanti. Se
foo
è un collegamento simbolico a una directory, stat foo
esaminerà il collegamento simbolico mentre stat foo/
esaminerà la directory. In alternativa, cerca stat -L
e usalo forse.
--
è nel caso $(pwd)
o $VARIABLE_PATH
inizia con -
(vedere la linea guida 10 qui ).
Ci sono readlink -f
(anche menzionati nell'altra risposta) e realpath
utilità. Uno di questi potrebbe essere un approccio migliore di stat
. Dipende da quali aspetti dei percorsi sono importanti per te. Differenze principali:
- Se
/foo/bar/
è un attacco bind, /moo/baz/
allora stat --format=%d:%i
ti dirà che sono uguali, ma readlink
o realpath
li considererà diversi.
- La situazione si complica con i collegamenti simbolici e
..
. Vedi man 1 realpath
, in particolare -L
e le -P
opzioni.
Con i link simbolici coinvolti, se il tuo script modifica la directory verso l'alto (verso /
, ad esempio cd ..
), potresti ottenere risultati diversi a seconda di dove inizi, anche se stat
o readlink -f
dice che i due punti di partenza sono gli stessi (confronta Perché ls ..
mostra il vero contenuto genitore quando io ' m all'interno di una directory di link simbolici? ). Considera questo approccio:
# early in the script
set -P
cd . # seems like no-op but updates the PWD variable to physical path
Con i montaggi di bind coinvolti, se lo script modifica la directory, potresti ottenere risultati diversi a seconda di dove inizi, anche se stat
dice che i due punti di partenza sono gli stessi. Considera l'esempio con /foo/bar/
e /moo/baz/
(già introdotto sopra). È ovvio che /foo/
potrebbe essere completamente diverso da /moo/
. Ma /foo/bar/abc
può anche essere diverso dal /moo/baz/abc
fatto che qualsiasi abc
potrebbe essere un attacco indipendente a qualcos'altro. Quindi non solo cd ..
potresti metterti in un posto diverso, ma anche cd abc
.
Bene, abc
potrebbe essere un file. Cosa succede se si associa un altro file a /moo/baz/abc
ma non a /foo/bar/abc
? I file percepiti saranno diversi anche se stat
dice che sei nello stesso posto!
A causa di questi problemi potresti davvero preferire readlink
o realpath
esagerare stat
.
stat
, readlink
E realpath
non sono richieste, POSIX. Nel tuo caso una soluzione portatile può apparire così:
a="$(cd -P -- "expected-subdir" && pwd -P)" || exit 1
b="$(cd -P -- "$VARIABLE_PATH/expected-subdir" && pwd -P)" || exit 1
[ "$a" = "$b" ] || { printf "Not the same path.\n" >&2; exit 2; }
Funziona andando cd
su entrambi i percorsi e recuperandolo pwd
. Queste operazioni sono esplicitamente costrette ad agire "fisicamente" ( -P
).
set -P
non è neanche POSIX. Se si desidera "emulare" la shell POSIX set -P
, sostituire cd
e pwd
:
cd() { command cd -P "$@"; }
pwd() { command pwd -P "$@"; }
POSIX richiede che l'ultimo -P
o l' -L
opzione abbia effetto, quindi pwd -L
recupera comunque il percorso logico anche se la funzione "inietta" -P
; lo stesso per cd -L
.
find path/to/dir/ -maxdepth 0 -printf %i\\n
quanto stampa solo l'inode e non il nome. Ilmaxdepth 0
impedisce una profonda ricerca. Per maggiore sicurezza, aggiungi%D
poiché gli inode sono unici per disco, non a livello di sistema.