Tragbarer Weg, um die Inode-Nummer zu finden

10

Zuerst benutzte ich stat -c %i file( um das Vorhandensein eines Gefängnisses zu erkennen ), was auf jeder Linux-Distribution unter der Sonne zu funktionieren schien. Unter OS X musste ich verwenden ls -i file | cut -d ' ' -f 1.

Gibt es eine Möglichkeit, die Inode-Nummer einer Datei in einem Shell-Skript zu finden, das auf * nix-Plattformen portierbar ist und nicht von dem notorisch launischen abhängt ls?

l0b0
quelle
1
Sie interessieren sich vielleicht für oder haben bessere Antworten auf: Wie kann ich sagen, dass ich in einer Chroot renne? .
Gilles 'SO - hör auf böse zu sein'
Können Sie etwas über das "notorisch launische ls" erzählen?
Jlliagre
@jlliagre: Andere haben es schon besser gemacht.
10b0
Okay, für solche Dateien siehe meine Antwort.
11.

Antworten:

11

Mögliche Lösung: Die POSIX-Spezifikation fürls gibt an -i, dass sie möglicherweise portabel ist. Kennt jemand eine beliebte Implementierung, lsdie dies nicht unterstützt, oder druckt sie anders als im folgenden Beispiel:

$ ls -di /
2 /
l0b0
quelle
3
@jlliagre: Bitte vor dem Posten lesen. Der statBefehl funktionierte nicht unter OS X, sondern unter ls -dibeiden.
10b0
1
Sogar Busybox lshat -dund -ials obligatorische Funktionen (obwohl lsselbst optional ist, wie alles andere).
Gilles 'SO - hör auf böse zu sein'
1
Michael Missverständnis war genau das, was ich kommentierte. Es ist keinen unhöflichen und unverdienten Kommentar "Vor dem Posten lesen" wert.
Jlliagre
2
Es gibt Ausnahmen: lsBei -iFrontpads mit Leerzeichen auf mindestens Solaris 10 (möglicherweise Solaris 11 habe ich nicht überprüft). Es sieht so aus, als ob dies das traditionelle Verhalten war, das auf Unix Version 7 zurückgeht. Ich vermute, dass viele der Corporate * nix-Varianten dieses Verhalten beibehalten haben (ich habe jedoch nur Solaris 10 zur Hand). Soweit ich das beurteilen kann , ist es portabel zu erwarten, dass die erste Nicht-Leerzeichen-Zeichenfolge die Inode ist, wenn Sie etwas verwenden, das Felder in beliebigen Leerzeichen richtig abgrenzt (also nicht cut, sondern zum Beispiel awkoder nur die eigene Feldaufteilung der Shell) Nummer.
mtraceur
1
@ l0b0 Ja. Es erfordert masochistisches Engagement: eine Reihe von Studien / Tests und Auswendiglernen, um die Renditen ständig zu verringern. Es ist möglich, zumindest für eine Definition von "tragbar", aber es ist keine angenehme Erfahrung.
mtraceur
2

Dies sollte portabel sein und mit Dateinamen arbeiten, die Leerzeichen, Zeilenumbrüche oder andere ungerade Zeichen enthalten, was zu dem notorisch launischen ls-Verhalten führt.

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

Um die Portabilität zu erhöhen, können Sie auch eine plattformspezifische Wrapper-Funktion (hier genannt statinode()) um den statBefehl implementieren , die auf der Ausgabe von uname -s(siehe uname ) basieren kann .

ls würde nur als Fallback-Option benötigt.

(
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
)
Jeff
quelle
0

statist Teil des GNU Coreutils- Pakets. OSX verwendet eine andere statImplementierung (vermutlich eine BSD-basierte), die nicht dieselben Befehlszeilenargumente verwendet.

Sie können GNU Coreutils jederzeit unter OSX installieren. Das hilft natürlich nicht, wenn Sie eine Lösung benötigen, die auf OSX-Systemen ohne GNU Coreutils funktioniert.

Wenn ich die Manpage zu OSX stat (1) richtig lese , stat -f %i fileverhält sich OSX stat -c %i fileunter OSX wie die Coreutils-Version. (Es statist eine andere Sache, stat --version >/dev/nullfestzustellen, welche Version von Ihnen vorhanden ist. Sie können es versuchen . Wenn dies erfolgreich ist, haben Sie die GNU Coreutils-Version.)

Die ls -diLösung ist mehr tragbar und weniger Probleme, aber dies ist eine Alternative.

Keith Thompson
quelle
0

Eine andere Lösung:

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

Sie können wahrscheinlich davon ausgehen, dass Perl installiert ist.

Keith Thompson
quelle
0

Ähnlich wie Jeffs Ansatz statkönnte auch direkt getestet werden.

(
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
)
ianc
quelle