起初我用stat -c %i file
(来帮助检测监狱的存在),它似乎可以在任何 Linux 发行版上运行。在 OS X 上我必须使用ls -i file | cut -d ' ' -f 1
.
有没有某种方法可以在 shell 脚本中查找文件的索引节点号,该脚本可以跨 *nix 平台移植并且不依赖于臭名昭著的反复无常ls
?
答案1
可能的解决方案:POSIX 规范ls
指定-i
,所以也许它是可移植的。有谁知道一个流行的ls
实现不是支持这一点,或者以与以下示例不同的方式打印它:
$ ls -di /
2 /
答案2
这应该是可移植的,并且可以处理包含空格、换行符或其他奇怪字符的文件名出了名的反复无常ls的行为。
filename="whatever file name"
find . -name "$filename" -exec sh -c 'ls -di "$0" | head -1' {} \;
答案3
为了提高可移植性,您还可以围绕命令实现特定于平台的包装函数(此处称为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
)
答案4
另一个解决方案:
#!/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 已安装。