Solução possível: A especificação POSIX para ls
especifica -i
, então talvez é portável. Alguém sabe de uma implementação popular de ls
que não suporta isso, ou imprime de forma diferente do seguinte exemplo:
$ ls -di /
2 /
Primeiro, usei stat -c %i file
(para ajudar a detectar a presença de uma cadeia ), que parecia funcionar em qualquer distribuição Linux sob o sol. No OS X 'eu tive que usar ls -i file | cut -d ' ' -f 1
.
Existe alguma maneira de encontrar o número de inode de um arquivo em um script de shell que seja portátil em plataformas * nix e não dependa do notoriamente caprichoso ls
?
Solução possível: A especificação POSIX para ls
especifica -i
, então talvez é portável. Alguém sabe de uma implementação popular de ls
que não suporta isso, ou imprime de forma diferente do seguinte exemplo:
$ ls -di /
2 /
Isso deve ser portável e funcionar com nomes de arquivos que contenham espaços, novas linhas ou outros caracteres estranhos, levando ao comportamento notoriamente caprichoso de ls.
filename="whatever file name"
find . -name "$filename" -exec sh -c 'ls -di "$0" | head -1' {} \;
Para aumentar a portabilidade, você também pode implementar uma função de wrapper específica da plataforma (aqui chamada statinode()
) em torno do comando stat
que pode ser baseado na saída de uname -s
(consulte uname ).
ls
seria necessário apenas como opção de 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
)
stat
faz parte do pacote GNU Coreutils . O OSX usa uma implementação diferente de stat
(presumivelmente baseada em BSD) que não aceita os mesmos argumentos de linha de comando.
Você sempre pode instalar o GNU Coreutils no OSX. Claro que isso não ajuda se você precisar de uma solução que funcione em sistemas OSX que não possuam o GNU Coreutils.
Ou, se eu estiver lendo o stat do OSX (1) man page corretamente, stat -f %i file
no OSX se comporta como stat -c %i file
usando a versão Coreutils. (Determinar qual versão de stat
você tem é outra questão; você pode tentar stat --version >/dev/null
; se tiver sucesso, você terá a versão GNU Coreutils.)
A solução ls -di
é mais portável e menos problemática, mas isso é uma alternativa.
Outra solução:
#!/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";
Você provavelmente pode presumir com segurança que o Perl está instalado.
Similar à abordagem de jeff, stat
poderia ser testado diretamente também.
(
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
)