Manière portable de trouver le numéro d'inode


10

Au début, j'ai utilisé stat -c %i file(pour aider à détecter la présence d'une prison ), qui semblait fonctionner sur n'importe quelle distribution Linux sous le soleil. Sur OS X ', je devais utiliser ls -i file | cut -d ' ' -f 1.

Existe-t-il un moyen de trouver le numéro d'inode d'un fichier dans un script shell qui est portable sur les plates-formes * nix et ne dépend pas des notoirement capricieux ls?


1
Vous pourriez être intéressé par, ou avoir de meilleures réponses, comment puis-je savoir que je cours dans un chroot? .
Gilles 'SO- arrête d'être méchant'

Pouvez-vous élaborer sur les «ls notoirement capricieux»?
jlliagre

@jlliagre: D'autres l'ont déjà fait mieux.
l0b0

D'accord, pour de tels fichiers, voir ma réponse.
jlliagre

Réponses:


11

Solution possible: La spécification POSIX pourls spécifie -i, alors peut-être qu'elle est portable. Quelqu'un connaît-il une implémentation populaire lsqui ne prend pas en charge cela ou l'imprime d'une manière différente de l'exemple suivant:

$ ls -di /
2 /

3
@jlliagre: Veuillez lire avant de poster. La statcommande ne fonctionnait pas sur OS X, ls -difonctionnait sur les deux.
l0b0

1
Même Busybox lsa -det -icomme fonctionnalités obligatoires (bien que lslui-même soit facultatif, comme tout le reste).
Gilles 'SO- arrête d'être méchant'

1
Le malentendu de Michael était précisément ce que je commentais. Cela ne vaut pas un commentaire assez grossier et immérité "lire avant de poster".
jlliagre

2
Il y a des exceptions à cela: lsavec des -ifront-pads avec des espaces sur au moins Solaris 10 (peut-être Solaris 11, je n'ai pas vérifié). Il semble que ce soit le comportement traditionnel remontant à la version 7 d'Unix, donc je soupçonne que de nombreuses versions d'entreprise * nix ont conservé ce comportement (je n'ai que Solaris 10 sous la main cependant). Si près que je sache, si vous utilisez quelque chose qui délimite correctement les champs dans des espaces blancs arbitraires (donc, non cut, mais par exemple awkou juste le propre fractionnement des champs du shell), il est portable de s'attendre à ce que la première chaîne non blanche soit l'inode nombre.
mtraceur

1
@ l0b0 Ouais. Cela nécessite un dévouement masochiste: un tas d'études / tests et de mémorisation pour des rendements constamment décroissants. C'est possible, du moins pour une certaine définition de "portable", mais ce n'est pas une expérience agréable.
mtraceur

2

Cela devrait être portable et fonctionner avec des noms de fichiers contenant des espaces, des sauts de ligne ou d'autres caractères étranges conduisant au comportement ls notoirement capricieux .

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

1

Pour augmenter la portabilité, vous pouvez également implémenter une fonction d'encapsulation spécifique à la plate-forme (appelée ici statinode()) autour de la statcommande qui peut être basée sur la sortie de uname -s(voir uname ).

ls serait nécessaire comme option de secours uniquement.

(
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

statfait partie du paquet GNU Coreutils . OSX utilise une statimplémentation différente (vraisemblablement basée sur BSD) qui ne prend pas les mêmes arguments de ligne de commande.

Vous pouvez toujours installer GNU Coreutils sur OSX. Bien sûr, cela n'aide pas si vous avez besoin d'une solution qui fonctionne sur des systèmes OSX qui n'ont pas GNU Coreutils.

Ou, si je lis correctement la page de manuel OSX stat (1) , stat -f %i filesur OSX se comporte comme l' stat -c %i fileutilisation de la version Coreutils. (Déterminer quelle version de statvous avez est une autre affaire; vous pouvez essayer stat --version >/dev/null; si elle réussit, vous avez la version GNU Coreutils.)

La ls -disolution est plus portable et moins problématique, mais c'est une alternative.


0

Une autre solution:

#!/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";

Vous pouvez probablement supposer en toute sécurité que Perl est installé.


0

Similaire à l'approche de Jeff, statpourrait également être testé directement.

(
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
)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.