Por que `cp` e` rm` tratam diretórios separadamente?

10

Por que ferramentas gostam cpe rmtratam diretórios separadamente dos arquivos regulares? Ambos exigem que o usuário especifique explicitamente que ela quer um comportamento recursivo, ou então eles não vão lidar com os diretórios.

Minha primeira interação (um tempo atrás) com computadores foi em um ambiente Windows / GUI / apontar e clicar / arrastar e soltar, sempre parecia natural que essas operações se comportassem da mesma forma, independentemente do destino.

Esse comportamento me frustra particularmente quando eu dou comandos com curingas. E se eu quiser remover tudo em um diretório ( *), exceto os subdiretórios não vazios ?

Só posso imaginar que esse é algum tipo de recurso de segurança para impedir que o usuário atire no próprio pé, mas isso contradiz minha compreensão de alguns princípios do Unix:

  • O Unix geralmente não protege o usuário de si mesma. Sempre assumiu que o usuário sabe o que está fazendo.
  • Para o Unix, tudo é um arquivo. Um diretório não é apenas outro arquivo? Por que eles são tratados de maneira diferente?

Minhas perguntas:

  • Esse comportamento é decorrente de uma limitação técnica ou é uma escolha deliberada?

E no caso deste último,

  • existem relatos históricos das razões que motivaram essa escolha?
rahmu
fonte
Para rm, pelo menos, se quiser ignorar a diferença entre arquivos e diretórios, você pode colocar no seu ~/.bashrcarquivo: alias rm='rm -r'.
precisa saber é o seguinte
1
Veja também a pergunta diferente, mas relacionada unix.stackexchange.com/questions/46066/…
derobert
1
Você não pode comparar cp e rm com o gerenciador de arquivos do Windows. Inicie o cmd.exe e tente copiar e excluir e compare o comportamento.
1--13

Respostas:

11

Por que o programa unix mv de Derobert não precisa da opção -R (recursiva) para diretórios, mas o cp precisa? basicamente responde à sua pergunta: copiar ou remover um arquivo regular é diferente de fazer a mesma operação com um diretório, porque para um diretório você precisa processar todos os arquivos nele contidos. Portanto, a operação é fundamentalmente diferente.

Também digno de nota é que existe um utilitário especial rmdirque só pode atuar em diretórios vazios. Sem verificar os fatos, isso leva à conclusão de que talvez originalmente rmapenas fosse possível remover os não-diretórios e a remoção profunda precisava ser alcançada usando-se recursivamente rmpara esvaziar os diretórios e depois rmdirremovê-los.

peterph
fonte
rmdirtambém é o nome da chamada do sistema usada para excluir um diretório. O diretório deve estar vazio para a chamada do sistema e o utilitário com o mesmo nome é apenas "front-end", semelhante ao unlinkcomando e utilitário.
Jordanm #
Exatamente - é isso que me leva a acreditar que originalmente rmpoderia ter sido incapaz de remover diretórios (porque os utilitários de linha de comando geralmente são apenas wrappers relativamente simples em torno de syscalls).
Peterph
O título da minha pergunta pode enganar ao pensar que estou perguntando sobre os detalhes técnicos. Eu estava perguntando se é uma escolha deliberada. Gostaria de saber se sou o único a pensar que, do ponto de vista do usuário final, esse comportamento é inconsistente. Estou aceitando a sua resposta porque indiretamente responde à minha pergunta: limitações técnicas nos recursos internos do Unix (no nível de syscall) parecem ser a origem desse comportamento, e o legado provavelmente nos impede de fazê-lo de qualquer outra maneira hoje. Os "invólucros simples em torno dos syscalls" não devem nos dar comportamentos mais inteligentes?
rahmu
2
Do ponto de vista do usuário final, parece realmente estranho, mas você realmente estava perguntando sobre os motivos. :) Quanto aos invólucros - tudo depende de quão "simples" eles são (e do que você ainda deseja chamar de "simples"). rmDefinitivamente, o moderno não é apenas um invólucro simples (é capaz de remover arquivos mroe de uma vez e também diretórios). Se você não gostar de dar a -ropção, use a funcionalidade de alias do seu shell ou crie seu próprio wrapper que o colocará no lugar (o que seria mais lento, mas independente do shell que você está usando).
Peterph
2

Em alguns tipos de UNIX, a página de manual do rm especifica como um comando para desvincular um arquivo.
No UNIX, arquivos são objetos no sistema de arquivos chamados Inodes, sem nomes ou localizações além de um ID no sistema de arquivos. Seus nomes são referências a eles em vários diretórios, que são um tipo de arquivo que indexa os arquivos (ou diretórios, uma vez que são arquivos) listados nele.
Ao desassociar um arquivo, a contagem de referência do arquivo diminui e, quando chega a 0, na verdade é excluída, pois é marcada como livre pelo sistema de arquivos e seus blocos / extensões também são marcados como livres.

Se você conseguiu rm um diretório sem desvincular os arquivos nele primeiro, chegará a um ponto em que você possui inodes referenciados no seu sistema de arquivos, mas não pode ser acessado por qualquer meio normal.
Como há uma referência a eles de acordo com a contagem de referências, eles não são marcados como excluídos e se tornam arquivos perdidos.
Isso fica ainda mais complexo quando os "arquivos" perdidos são diretórios e, como tal, aumenta a quantidade potencial de armazenamento perdido no sistema de arquivos.

Então rm -r foi adicionado, como um recurso para facilitar a vida dos usuários do UNIX, em detrimento do "espírito UNIX" padrão, pois é mais complexo que os utilitários clássicos do UNIX, pois desce para diretórios e remove arquivos,

Além disso, no início do UNIX, os sistemas não tinham muita memória e o mapeamento da estrutura recursiva de um diretório tinha uma penalidade no desempenho, e às vezes era impossível fazer isso sem dividir o trabalho.

cp, lê um arquivo e o copia, bloco por bloco. Se fosse para copiar um diretório da mesma forma que um arquivo, ele adicionaria referências aos arquivos dentro sem aumentar sua contagem de referências, o que poderia levar a dados inconsistentes (se estiver lendo / gravando em um inode cujos blocos estão marcados como livres desde a sua inode original foi excluído), perda de dados - uma vez que a exclusão da última referência (conhecida) a um arquivo pode fazer com que seu número de inode seja reciclado.

Para a multidão tl; dr:
Diretórios no UNIX são um tipo de arquivo, isso é verdade, mas como as informações contidas neles são tratadas de maneira diferente pelo sistema, pois são metadados do sistema de arquivos, os comandos que manipulam arquivos não podem funcionar em diretórios sem um diretório. mudança de comportamento para manipular também os metadados dependentes.

Didi Kohen
fonte