No
[ -f "$file" ]
o [comando faz uma stat()(não lstat()) chamada do sistema no caminho armazenado $filee retorna true se a chamada do sistema for bem-sucedida e o tipo de arquivo retornado por stat()" regular ".
Portanto, se [ -f "$file" ]retorna true, você pode dizer que o arquivo existe e é um arquivo regular ou um link simbólico que eventualmente está sendo resolvido para um arquivo regular (ou pelo menos era no momento do stat()).
No entanto, se retornar falso (ou se [ ! -f "$file" ]ou ! [ -f "$file" ]retornar verdadeiro), há muitas possibilidades diferentes:
- o arquivo não existe
- o arquivo existe, mas não é regular (pode ser um dispositivo, fifo, diretório, soquete ...)
- o arquivo existe, mas você não tem permissão de pesquisa para o diretório pai
- o arquivo existe, mas esse caminho para acessá-lo é muito longo
- o arquivo é um link simbólico para um arquivo normal, mas você não tem permissão de pesquisa para alguns dos diretórios envolvidos na resolução do link simbólico.
- ... qualquer outro motivo pelo qual a
stat()chamada do sistema possa falhar.
Em suma, deve ser:
if [ -f "$file" ]; then
printf '"%s" is a path to a regular file or symlink to regular file\n' "$file"
elif [ -e "$file" ]; then
printf '"%s" exists but is not a regular file\n' "$file"
elif [ -L "$file" ]; then
printf '"%s" exists, is a symlink but I cannot tell if it eventually resolves to an actual file, regular or not\n' "$file"
else
printf 'I cannot tell if "%s" exists, let alone whether it is a regular file or not\n' "$file"
fi
Para ter certeza de que o arquivo não existe, precisaríamos que a stat()chamada do sistema retornasse com um código de erro de ENOENT( ENOTDIRnos diz que um dos componentes do caminho não é um diretório, outro caso em que podemos dizer que o arquivo não existe) existir por esse caminho). Infelizmente, o [comando não nos informa disso. Ele retornará false se o código de erro é ENOENT, EACCESS (permissão negada), ENAMETOOLONG ou qualquer outra coisa.
O [ -e "$file" ]teste também pode ser feito com ls -Ld -- "$file" > /dev/null. Nesse caso, lsinformará o motivo da stat()falha, embora as informações não possam ser facilmente usadas programaticamente:
$ file=/var/spool/cron/crontabs/root
$ if [ ! -e "$file" ]; then echo does not exist; fi
does not exist
$ if ! ls -Ld -- "$file" > /dev/null; then echo stat failed; fi
ls: cannot access '/var/spool/cron/crontabs/root': Permission denied
stat failed
Pelo menos lsme diz que não é porque o arquivo não existe que falha. É porque ele não pode dizer se o arquivo existe ou não. O [comando apenas ignorou o problema.
Com o zshshell, você pode consultar o código de erro com a $ERRNOvariável especial após o [comando com falha e decodificar esse número usando a $errnosmatriz especial no zsh/systemmódulo:
zmodload zsh/system
ERRNO=0
if [ ! -f "$file" ]; then
err=$ERRNO
case $errnos[err] in
("") echo exists, not a regular file;;
(ENOENT|ENOTDIR)
if [ -L "$file" ]; then
echo broken link
else
echo does not exist
fi;;
(*) syserror -p "can't tell: " "$err"
esac
fi
(cuidado, o $errnossuporte foi quebrado com algumas versões de zshquando construído com versões recentes dogcc ).