Estou tentando emular o processo de resolução do caminho (consulte a página de manual path_resolution) em sistemas como o Unix.
Meu sistema operacional é Linux com GNU coreutils 8.7.
Para esclarecer o significado de '/' à direita na resolução, fiz as seguintes coisas em um shell:
mkdir this_is_dir
ln -s this_is_dir this_is_link
rm this_is_link
Tudo estava bem, porque this_is_link é um link simbólico e eu apenas o removi. Mas enquanto tenta:
mkdir this_is_dir
ln -s this_is_dir this_is_link
rm this_is_link/
Ecoou rm: cannot remove 'this_is_link/': Is a directory
Bem, o '/' à direita causou o seguinte link simbólico, pensei. Então, eu tentei outro comando:rmdir this_is_link/
E um resultado engraçado saiu: rmdir: failed to remove 'this_is_link/': Not a directory
Não o que eu esperava. Então, pedi ao meu amigo para confirmar se o mesmo resultado poderia ser obtido em seu sistema. Ele tinha uma versão inferior do coreutils do que eu. E o resultado foi incrível, não importa rm
ou rmdir 'this_is_link/'
, Not a directory
ocorre o mesmo erro .
E outro amigo acabou de experimentar no Mac OS, o resultado é: rm
=> 'É um diretório', rmdir
=> o diretório foi excluído com sucesso, o link permaneceu .
Há alguma especificação sobre o comportamento exato da resolução do caminho?
Respostas:
A especificação POSIX / Single Unix especifica que um nome de caminho com uma barra final deve se referir a um diretório (consulte as definições de base §4.11 resolução do nome de caminho ).
foo/
é de fato definido como equivalente afoo/.
(para propósitos de resolução de caminho, não ao manipular nomes de arquivos;basename
edirname
ignora barras finais). A maioria das implementações respeita isso, mas existem algumas exceções.Isso explica o comportamento de
rm this_is_link/
: é equivalente arm this_is_link/.
, onde o argumento é claramente um diretório.rmdir this_is_link/
da mesma forma, consulte o diretório O fato de isso não acontecer na sua máquina é um bug no GNU coreutils. O OSX está se comportando corretamente aqui.fonte
Minha vez:
Aliás, a resolução do caminho tem muito pouco a ver com isso, apenas parece '' rm '' cortando uma esquina em vez de (corretamente) invocar "stat" em um argumento (que é o que rmdir está fazendo).
Felicidades.
fonte
rm
chama stat (bem, newfstatat, na verdade, com aAT_SYMLINK_NOFOLLOW
opção) e se recusa a continuar, enquanto rmdir realmente chama rmdir (2), mas recebeENOTDIR
.AT_SYMLINK_NOFOLLOW
impedirá que ele siga o link simbólico, portanto, a rm deve excluir o próprio link em vez de imprimir "Não é um diretório" que não corresponde à circunstância.stat
estat -L
difere apenas se o argumento for fornecido sem uma barra final.rm
está se comportando corretamente ermdir
não está. O final/
deve forçá-los a tratar seus argumentos como um diretório, de acordo com o padrão POSIX. Veja minha resposta para referências .