Qual é a diferença entre 'rm' e 'unlink'?

55

Supondo que você saiba que o destino é um link simbólico e não um arquivo, existe alguma diferença entre usar rme unlinkremover o link?

IQAndreas
fonte
3
Isso é muito bem abordado no ServerFault: serverfault.com/questions/38816/…
slm
@ slm ♦ As respostas correspondem a essa pergunta, mas essa pergunta é diferente, diz: "Supondo que você saiba que o destino é um link simbólico e não um arquivo".
Stéphane Gourichon 21/03/2015
Não parece que você aceitou uma resposta aqui @IQAndreas. Por favor, faça-o se eles o ajudaram.
Gray

Respostas:

56

Sempre que você tiver esse tipo de pergunta, é melhor conceber um pequeno teste para ver o que realmente está acontecendo. Para isso você pode usar strace.

desvincular

$ touch file1
$ strace -s 2000 -o unlink.log unlink file1

rm

$ touch file1
$ strace -s 2000 -o rm.log rm file1

Quando você olha os 2 arquivos de log resultantes, pode "ver" o que cada chamada está realmente fazendo.

Demolir

Com unlinkisso, é chamada a chamada do unlink()sistema:

....
mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f6d025cc000
close(3)                                = 0
unlink("file1")                         = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
....

Com rmum caminho um pouco diferente:

....
ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
newfstatat(AT_FDCWD, "file1", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
geteuid()                               = 1000
newfstatat(AT_FDCWD, "file1", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
faccessat(AT_FDCWD, "file1", W_OK)      = 0
unlinkat(AT_FDCWD, "file1", 0)          = 0
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
...

O sistema chama unlink()e unlinkat()é essencialmente o mesmo, exceto pelas diferenças descritas nesta página de manual: http://linux.die.net/man/2/unlinkat .

excerto

A chamada do sistema unlinkat () opera exatamente da mesma maneira que unlink (2) ou rmdir (2) (dependendo de os sinalizadores incluírem ou não o sinalizador AT_REMOVEDIR), exceto pelas diferenças descritas nesta página de manual.

Se o nome do caminho fornecido no nome do caminho for relativo, será interpretado em relação ao diretório referido pelo descritor de arquivo dirfd (em vez de relativo ao diretório de trabalho atual do processo de chamada, como é feito por unlink (2) e rmdir (2) ) para um nome de caminho relativo).

Se o nome do caminho fornecido no nome do caminho for relativo e dirfd for o valor especial AT_FDCWD, o nome do caminho será interpretado em relação ao diretório de trabalho atual do processo de chamada (como unlink (2) e rmdir (2)).

Se o nome do caminho fornecido no nome do caminho for absoluto, o dirfd será ignorado.

slm
fonte
11
Como está dando AT_FDCWD, efetivamente não há diferença entre unlinke unlinkat.
Barmar
6
Fico feliz em ler esta resposta, porque eu apenas "aprendi a pescar" de uma maneira poderosa e flexível, quando frequentemente compro um peixe ou, às vezes, "aprendo a pescar" de uma maneira básica em SO :-)
sábio
22

POSIX especifica que o unlinkutilitário chama a unlinkfunção da biblioteca C e nada mais. Não precisa de opção. Se você passar um nome de caminho válido para algo que não é um diretório e se tiver permissões de gravação no diretório em que esse objeto mora, ele unlinkserá removido.

rmé um comando tradicional do Unix que possui algumas outras funcionalidades e não é um superconjunto unlink(veja abaixo).

Em primeiro lugar, rmrealiza verificações de segurança. Se você tentar rmum objeto para o qual você não tem permissões de gravação (que são irrelevantes para a sua capacidade de removê-lo: as permissões diretamente são!), No rmentanto, recusa, a menos que -fseja especificado. rmnormalmente reclama se o arquivo não existe, assim como unlink; no entanto com -f, rmnão reclama. Isso é frequentemente explorado em Makefiles ( clean: @rm -f $(OBJS) ...), portanto make cleannão falha quando não há nada a remover.

Em segundo lugar, rmtem a -iopção de confirmar interativamente a exclusão.

Em terceiro lugar, rmé necessário -rremover recursivamente um diretório, o que unlinknão é necessário, pois a função da biblioteca C não faz isso.

O unlinkutilitário não é exatamente um despojado rm. Ele executa um subconjunto do que rmfaz, mas possui semântica que é uma combinação de rm with -f e rm without -f .

Suponha que você queira apenas remover um arquivo comum, independentemente de quais sejam suas próprias permissões. Além disso, suponha que você queira que o comando falhe se o arquivo não existir ou por qualquer outro motivo. Nem rm filenem rm -f fileatende aos requisitos. rm filerecusará se o arquivo não for gravável. Mas rm -f filedeixará de reclamar se o arquivo estiver faltando. unlink filefaz o trabalho.

unlinkfoi provavelmente introduzido porque rmé muito inteligente: às vezes você quer apenas a unlinksemântica pura do Unix : "faça esta entrada de diretório desaparecer se as permissões de diretório permitirem" .

Kaz
fonte
2
Esta é a resposta mais clara aqui. Na verdade, fornece o caso de uso para, em unlinkvez de apenas descrever as diferenças.
Wildcard
19

Com um único arquivo, rm e unlink fazem a mesma tarefa, remova o arquivo. Conforme definido pelo POSIX, rme unlinkambos chamam para desvincular () a chamada do sistema.

No GNU rm, ele chama a chamada do sistema unlinkat () , que é equivalente à função unlink()ou rmdir () , exceto no caso em que path especifica um caminho relativo.

Nota

Em alguns sistemas, unlinktambém é possível remover o diretório Pelo menos no sistema GNU, unlinknunca pode excluir o nome de um diretório.

cuonglm
fonte