Портативний спосіб пошуку номера inode


10

Спочатку я використовував stat -c %i file(щоб допомогти виявити наявність в'язниці ), який, здавалося, працює на будь-якому дистрибутиві Linux під сонцем. На OS X 'довелося використовувати ls -i file | cut -d ' ' -f 1.

Чи є якийсь спосіб знайти номер inode файла в скрипті оболонки, який переноситься через * nix-платформи і не залежить від горезвісно примхливих ls?


1
Можливо, вас зацікавить чи краще відповіді на те, як я можу сказати, що я бігаю в хрото? .
Жил "ТАК - перестань бути злим"

Чи можете ви детальніше розповісти про "горезвісно примхливий лс"?
jlliagre

@jlliagre: Інші вже зробили це краще.
l0b0

Добре, для таких файлів дивіться мою відповідь.
jlliagre

Відповіді:


11

Можливе рішення: специфікація POSIX дляls специфікацій -i, тому, можливо, вона є портативною. Хтось знає про популярну реалізацію, lsяка цього не підтримує, або друкує її іншим чином із наступного прикладу:

$ ls -di /
2 /

3
@jlliagre: Будь ласка, прочитайте перед публікацією. statКоманда не працює на OS X, ls -diпрацював на обох.
l0b0

1
Навіть Busybox lsмає -dі -iяк обов'язкові функції (хоча lsсам по собі необов’язковий, як і все інше).
Жил "ТАК - перестань бути злим"

1
Нерозуміння Майкла було саме тим, що я коментував. Не варто досить грубо і незаслужено "прочитати перед публікацією" коментар.
jlliagre

2
З цього є винятки: lsіз -iпередніми колодками з пробілами принаймні Solaris 10 (можливо, Solaris 11, я не перевіряв). Схоже, це було традиційне поведінка, що повертається до версії Unix 7, тому я підозрюю, що багато корпоративних * nix ароматів зберегли таку поведінку (хоча у мене є тільки Solaris 10 під рукою). Так що, як я можу сказати, якщо ви використовуєте щось, що належним чином розмежовує поля в довільному просторі пробілів (так, ні cut, але, наприклад, awkабо просто розбиття власного поля оболонки), переносно очікувати, що перший рядок, який не є пробілом, буде inode число.
mtraceur

1
@ l0b0 Так. Це вимагає мазохістської відданості: купа вивчення / тестування та запам'ятовування для постійного зменшення прибутку. Це можливо, принаймні для якогось визначення "портативного", але це не приємне враження.
mtraceur

2

Це повинно бути портативним і працювати з іменами файлів, що містять пробіли, нові рядки або інші непарні символи, що призводить до сумно примхливої поведінки ls.

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

1

Для збільшення портативності ви також можете реалізувати функцію обгортки, орієнтовану на платформу (тут називається statinode()) навколо statкоманди, яка може базуватися на результатах uname -s(див. Відмінити )

ls знадобиться лише як резервний варіант.

(
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

statє частиною пакету GNU Coreutils . OSX використовує іншу statреалізацію (імовірно, на базі BSD), яка не приймає однакових аргументів командного рядка.

Ви завжди можете встановити GNU Coreutils на OSX. Звичайно, це не допомагає, якщо вам потрібно рішення, яке працює в системах OSX, у яких немає GNU Coreutils.

Або якщо я читаю головну сторінку OSX stat (1) правильно, stat -f %i fileна OSX поводиться так, як stat -c %i fileвикористовувати версію Coreutils. (Визначення версії у statвас є іншою справою; ви можете спробувати stat --version >/dev/null; якщо вона успішна, у вас є версія GNU Coreutils.)

ls -diРішення більш компактно і менше клопоту, але це альтернатива.


0

Ще одне рішення:

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

Ви, напевно, можете сміливо припускати, що встановлено Perl.


0

Схожий на підхід Джеффа, також statможна було б протестувати безпосередньо.

(
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
)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.