Modo portatile per trovare il numero di inode


10

Inizialmente ho usato stat -c %i file(per aiutare a rilevare la presenza di una prigione ), che sembrava funzionare su qualsiasi distribuzione Linux sotto il sole. Su OS X 'ho dovuto usare ls -i file | cut -d ' ' -f 1.

C'è un modo per trovare il numero di inode di un file in uno script della shell che è portatile su piattaforme * nix e non dipende dal notoriamente capriccioso ls?


1
Potresti essere interessato o avere risposte migliori per, Come faccio a sapere che sto correndo in un chroot? .
Gilles 'SO- smetti di essere malvagio'

Puoi approfondire la "notoriamente capricciosa"?
jlliagre,

@jlliagre: altri l'hanno già fatto meglio.
l0b0

Va bene, per tali file, vedi la mia risposta.
jlliagre,

Risposte:


11

Possibile soluzione: le specifiche POSIX perls specifica -i, quindi forse è portatile. Qualcuno sa di un'implementazione popolare di lscui non supporta questo, o lo stampa in un modo diverso dal seguente esempio:

$ ls -di /
2 /

3
@jlliagre: leggi prima di pubblicare. Il statcomando non ha funzionato su OS X, ha ls -difunzionato su entrambi.
20

1
Anche Busybox lsha -de -icome funzionalità obbligatorie (anche lsse è facoltativo, come tutto il resto).
Gilles 'SO- smetti di essere malvagio' il

1
Il fraintendimento di Michael era proprio quello che stavo commentando. Non vale un commento piuttosto scortese e immeritato "leggi prima di pubblicare".
jlliagre,

2
Ci sono eccezioni a questo: lscon i -ifront pad con spazi su almeno Solaris 10 (possibilmente Solaris 11, non ho controllato). Sembra che questo fosse il comportamento tradizionale che risale alla versione 7 di Unix, quindi sospetto che molti dei gusti aziendali * nix abbiano mantenuto questo comportamento (ho solo Solaris 10 a portata di mano). Per quanto posso dire, se usi qualcosa che delinea correttamente i campi in spazi bianchi arbitrari (quindi, no cut, ma per esempio awko solo la divisione del campo della shell), è portatile aspettarsi che la prima stringa non di spazi bianchi sia l'inode numero.
mtraceur,

1
@ l0b0 Sì. Richiede dedizione masochistica: un sacco di studio / test e memorizzazione per rendimenti in costante diminuzione. È possibile, almeno per qualche definizione di "portatile", ma non è un'esperienza piacevole.
mtraceur,

2

Questo dovrebbe essere portatile e funzionare con nomi di file contenenti spazi, righe o altri caratteri strani che portano al comportamento notoriamente capriccioso .

filename="whatever file name"
find . -name "$filename" -exec sh -c 'ls -di "$0" | head -1' {} \;

1

Per aumentare la portabilità è anche possibile implementare una funzione wrapper specifica per la piattaforma (qui chiamata statinode()) attorno al statcomando che può essere basata sull'output di uname -s(vedi uname ).

ls sarebbe necessario solo come opzione di fallback.

(
shopt -s nocasematch nullglob    # using Bash
case "$(uname -s)" in
   # nocasematch alternative
   #[Ll][Ii][Ni][Uu][Xx]   )  statinode() { stat -c '%i' "$@"; return 0; };;
   "Linux"   )      statinode() { stat -c '%i' "$@"; return 0; };;
   "Darwin"  )      statinode() { stat -f '%i' "$@"; return 0; };;
   "FreeBSD" )      statinode() { stat -f '%i' "$@"; return 0; };;
           * )      statinode() { ls -id "$@" | cut -d ' ' -f 1; return 0; };;
esac
#export -f statinode
statinode / / / /
shopt -u nocasematch nullglob
)

0

statfa parte del pacchetto GNU Coreutils . OSX utilizza statun'implementazione diversa (presumibilmente basata su BSD) che non accetta gli stessi argomenti della riga di comando.

Puoi sempre installare GNU Coreutils su OSX. Ovviamente ciò non aiuta se hai bisogno di una soluzione che funziona su sistemi OSX che non hanno GNU Coreutils.

Oppure, se sto leggendo correttamente la pagina man stat di OSX stat (1) , stat -f %i filesu OSX si comporta come stat -c %i fileusare la versione di Coreutils. (Determinare quale versione di statte ha è un'altra questione; potresti provare stat --version >/dev/null; se ci riesce, hai la versione GNU Coreutils.)

La ls -disoluzione è più portatile e meno problemi, ma questa è un'alternativa.


0

Un'altra soluzione:

#!/usr/bin/perl

use strict;
use warnings;

die "Usage: $0 filename\n" if scalar @ARGV != 1;
my $file = $ARGV[0];
my @stat = stat $file;
die "$file: $!\n" if not @stat;
print "$stat[1]\n";

Probabilmente puoi tranquillamente supporre che Perl sia installato.


0

Simile all'approccio di Jeff, statpotrebbe anche essere testato direttamente.

(
if (stat -c '%i' / 1>/dev/null 2>&1; exit $?); then
   statinode() { stat -c '%i' "$@"; return 0; }
elif (stat -f '%i' / 1>/dev/null 2>&1; exit $?); then
   statinode() { stat -f '%i' "$@"; return 0; }
elif test -n "$(exec 2>/dev/null; ls -id / | cut -d ' ' -f 1)"; then
   statinode() { ls -id "$@" | cut -d ' ' -f 1; return 0; }
else
   echo 'Could not create statinode(). Exiting ...' && exit 1
fi
# export -f statinode
statinode / / / /
declare -f statinode
)
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.