Por que o programa unix mv não precisa da opção -R (recursiva) para diretórios, mas o cp precisa dele?

52

Sempre fico confuso quando preciso usar cp ou mv : "Preciso da opção -R ao trabalhar com dir?" Em GNU coreutils, cp precisa de -R e mv não.

Eu simplesmente não consigo encontrar nenhum motivo para que cp precise da opção -R para copiar dirs e mv não. Eu acho que cp ing dirs sem -R (mas se comportando recursivamente como se houvesse -R e como mv ) não causaria nenhum problema a não ser quebrar os hábitos de alguém ao usar a ferramenta.

Você conhece alguma explicação? Pode ser que tivesse uma razão há muito tempo?

Pergunta adicional: por que os desenvolvedores do coreutils não fazem cp copiar dirs de forma recursiva por padrão?

    
por rslnx 22.08.2012 / 14:28

3 respostas

43

Um diretório é (conceitualmente) um "arquivo" especial que contém uma lista de nomes e os números de inode para os quais os nomes apontam. Alguns dos nomes podem ser subdiretórios. Há uma entrada especial .. que aponta para o diretório pai.

Então, é claro, alterar o nome de um arquivo é fácil: basta alterar o nome na entrada do diretório, nada mais. Isso mantém se o arquivo é realmente um arquivo ou é um "arquivo" usado para armazenar o conteúdo de outro diretório. De fato, o mesmo rename syscall faz ambos.

Copiar, no entanto, é uma operação muito menos trivial. Você poderia apenas copiar o diretório "file", mas então você teria dois diretórios onde os arquivos são os mesmos (eles seriam hardlinks). Se você tivesse um sistema que permitisse hardlinks para diretórios, eles seriam, mas como nenhum sistema moderno permite isso, pelo menos para não-root, você precisa fazer essa cópia para cada subdiretório. Você pode pedir a cp para esse comportamento com cp -lR : -l para link físico, -R para essa recursão.

Mas deixar tudo vinculado provavelmente não é o que você deseja. Em vez disso, você deseja que cp copie cada arquivo. Essa é uma operação bastante cara: cada arquivo deve ser lido na memória e gravado de volta no disco em um segundo local. Na verdade, são necessários vários syscalls para abrir, ler, gravar e fechar os arquivos, e isso deve ser repetido para cada arquivo.

Os sistemas de arquivos tradicionais também funcionam dessa maneira no disco. Não há como copiar um monte de arquivos, além de passar por cada um deles individualmente e copiá-los, e esses são os tipos de sistemas de arquivos que estavam em uso quando os utilitários de linha de comando básicos foram projetados.

    
por 22.08.2012 / 14:50
19

Deixe-me começar por fazer outra pergunta:

Qual é a diferença entre cp e cp -R ?

Bem, sem o sinalizador -R , só é possível copiar arquivos, porque é bastante incomum alguém querer copiar um diretório de forma não recursiva: uma cópia não recursiva resultaria em um segundo nome para o diretório, apontando diretamente para a mesma estrutura de diretórios. Como isso raramente é o que as pessoas querem, e na verdade existe um programa separado que faz isso ( ln ), uma cópia não-recursiva de diretórios não é permitida.

Qual poderia então ser a diferença entre mv e mv -R ?

mv a b apenas renomeia uma única entrada no diretório, portanto, se um diretório for mv ed, seu conteúdo também será movido automaticamente. Nesse sentido, mv já fornece a propriedade recursiva, ou seja, a "renomeação" de todas as entradas no diretório renomeado, por exemplo, de a/1 a b/1 . Um mv que não faz isso, ou seja, que renomeia um diretório a para b , mas mantém a/1 como a/1 , não é o que as pessoas entendem quando se referem a mover algo: Quando você move um armário , o conteúdo do armário também é movido. Essa outra operação, movendo um diretório sem o seu conteúdo, também já está disponível, é chamada mkdir .

    
por 22.08.2012 / 15:10
6

Normalmente, quando estou confuso com a lógica Unix, vejo o Plan9 para ver como os inventores do Unix implementaram as mesmas tarefas anos depois, sem comprometer a compatibilidade com versões anteriores.

O Plan9 oferece as ferramentas cp e mv para operar somente com arquivos.

'cp f1 f2' creates f2 and copies f1's contents into it.
'mv f1 f2' renames f1 to f2 if f1 and f2 are in the same dir
           does 'cp f1 f2 && rm f1' else
           can rename dirs ('mv d1 d2') but will not move dir to another dir.

Para copiar um diretório, há dircp , que é realmente @{cd fromdir && tar c .} | @{cd todir && tar xT} (sintaxe do shell do rc)

Para mover um diretório, acho que há apenas dircp d1 d2 && rm -r d1

Acho que essa decisão de limitar cp e mv apenas para operações de arquivos (não dirs) traz mais clareza às operações de disco e usar tar para copiar árvores de arquivos é muito confortável para entender e criar scripts.

    
por 23.08.2012 / 14:36