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à statun errore.
- Le barre finali sono importanti. Se
fooè un collegamento simbolico a una directory, stat fooesaminerà il collegamento simbolico mentre stat foo/esaminerà la directory. In alternativa, cerca stat -Le usalo forse.
--è nel caso $(pwd)o $VARIABLE_PATHinizia con -(vedere la linea guida 10 qui ).
Ci sono readlink -f(anche menzionati nell'altra risposta) e realpathutilità. 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:%iti dirà che sono uguali, ma readlinko realpathli considererà diversi.
- La situazione si complica con i collegamenti simbolici e
... Vedi man 1 realpath, in particolare -Le le -Popzioni.
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 stato readlink -fdice 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 statdice 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/abcpuò anche essere diverso dal /moo/baz/abcfatto che qualsiasi abcpotrebbe essere un attacco indipendente a qualcos'altro. Quindi non solo cd ..potresti metterti in un posto diverso, ma anche cd abc.
Bene, abcpotrebbe essere un file. Cosa succede se si associa un altro file a /moo/baz/abcma non a /foo/bar/abc? I file percepiti saranno diversi anche se statdice che sei nello stesso posto!
A causa di questi problemi potresti davvero preferire readlinko realpathesagerare stat.
stat, readlinkE realpathnon 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 cdsu entrambi i percorsi e recuperandolo pwd. Queste operazioni sono esplicitamente costrette ad agire "fisicamente" ( -P).
set -Pnon è neanche POSIX. Se si desidera "emulare" la shell POSIX set -P, sostituire cde pwd:
cd() { command cd -P "$@"; }
pwd() { command pwd -P "$@"; }
POSIX richiede che l'ultimo -Po l' -Lopzione abbia effetto, quindi pwd -Lrecupera comunque il percorso logico anche se la funzione "inietta" -P; lo stesso per cd -L.
find path/to/dir/ -maxdepth 0 -printf %i\\nquanto stampa solo l'inode e non il nome. Ilmaxdepth 0impedisce una profonda ricerca. Per maggiore sicurezza, aggiungi%Dpoiché gli inode sono unici per disco, non a livello di sistema.