Ao mover o diretório atual, recebo "mv: não é possível mover `.' para `../dir/.': Dispositivo ou recurso ocupado"

Ao mover o diretório atual, recebo "mv: não é possível mover `.' para `../dir/.': Dispositivo ou recurso ocupado"
$ mv . ../general/
mv: cannot move `.' to `../general/.': Device or resource busy

Isso significa que o diretório atual é um dispositivo ou recurso ocupado e não pode ser movido? Por que é isso?

Responder1

Você não pode mover o diretório em que está. O processo atual é aquele que o mantém ocupado.

Em vez disso, suba um nível e nomeie o diretório atual anteriormente para movê-lo para o destino.

Responder2

Não é possível mover um ponto .. O ponto não é igual ao nome do diretório atual. Você pode pensar nisso .como um ponteiro para o diretório, mas não para o diretório em si, portanto,

$ pwd && echo $PWD && realpath .
/home/jimmij/tmp
/home/jimmij/tmp
/home/jimmij/tmp
$ mkdir tmp1 tmp2
$ mv tmp1/. tmp2/
mv: cannot move ‘tmp1/.’ to ‘tmp2/.’: Device or resource busy

não funciona, mas

cd tmp1
mv ../tmp1 ../tmp2

funciona bem, então na verdade vocêpodemova o diretório atual, embora alguns comandos possam ser confundidos após esta operação:

$ pwd && echo $PWD && realpath .
/home/jimmij/tmp/tmp1
/home/jimmij/tmp/tmp1
/home/jimmij/tmp/tmp2/tmp1
$ cd .
$ pwd && echo $PWD && realpath .
/home/jimmij/tmp/tmp2/tmp1
/home/jimmij/tmp/tmp2/tmp1
/home/jimmij/tmp/tmp2/tmp1

História semelhante com .., ou seja, diretório pai.

Em outras palavras, cada diretório deve conter pelo menos dois elementos: .e ... Você não pode movê-los ou excluí-los.

Responder3

O motivo pelo qual você está recebendo a mensagem:

mv: não é possível mover .' to../general/.': Dispositivo ou recurso ocupado

é devido à forma como o ., e ..funcionam além de mv. Quando você move algo no Unix, o mvcomando tenta desvincular tudo que faz referência ao inode do item que você está tentando mover. Nesse caso, esse seria o inode de qualquer diretório que .esteja referenciando.

Os "símbolos/links" .e ..estão vinculados a inodes e são, de certa forma, especiais. Você pode ler sobre a história deles aqui nas perguntas e respostas da U&L intituladas:Por que um novo diretório tem uma contagem de links físicos de 2 antes de qualquer coisa ser adicionada a ele?Se você já olhou para um diretório recém-criado, notará que ele sempre começa com uma contagem vinculada de 2. O motivo é devido à existência do .e ...

$ mkdir adir

$ ls -l | grep adir
drwxrwxr-x. 2 saml saml 4096 Oct  5 08:02 adir

$ ls -la adir/
total 8
drwxrwxr-x. 2 saml saml 4096 Oct  5 08:02 .
drwxrwxr-x. 3 saml saml 4096 Oct  5 08:02 ..

OBSERVAÇÃO:A referência para lsresultados, se você não tiver certeza, está aqui nestas perguntas e respostas sobre U&L intituladas:O que significam os campos na saída ls -al?

Portanto, eles não são nomes de diretórios reais, mas são "símbolos/links" vinculados a eles. Portanto, eles precisaram ser desvinculados antes de poder fazê-lo mv.

Bem, como o seu comando está usando o ., ele não pode ser desvinculado pelo mvcomando, daí a mensagem: "Dispositivo ou recurso ocupado".

Referências

Responder4

O Linux proíbe renomear qualquer caminho que termine no componente .ou .., retornando o erro EBUSY; o seguinte também falhará:

$ mkdir a a/aa
$ mv a/aa/.. b
mv: cannot move ‘a/aa/..’ to ‘b/..’: Device or resource busy

O código para isso está em namei.c::renameat. O último componente do nome do caminho, quando passado para várias funções, precisa ser do tipo LAST_NORM, não LAST_DOTou LAST_DOTDOT.

O FreeBSD retorna o erro EINVAL em cada um desses casos.


Só podemos adivinhar por que existe essa restrição.

A função rename() falhará se:
...
[EBUSY] O diretório nomeado por antigo ou novo estiver atualmente em uso pelo sistema ou outro processo e a implementação considerar isso um erro.

Pode-se considerar .que está atualmente em uso pelo processo. Mas observe que o Linux permite o seguinte, portanto, um diretório apenas em uso por algum processo não é suficiente para renamefalhar:

$ mkdir /tmp/t
$ cd /tmp/t
$ mv /tmp/t /tmp/t1
$ /bin/pwd
/tmp/t1

A razão para proibir a renomeação de .e ..é provavelmente "leva a menos confusão do usuário".

  • .normalmente é um link físico para a entrada do diretório em seu pai e é um tanto especial porque um processo sempre pode ser aberto .para acessar seu diretório de trabalho atual. Ser capaz de renomeá-lo seria contraproducente.
  • ..normalmente é um link físico para o pai do diretório e é um tanto especial porque a abertura de um processo ..obterá o diretório pai (ou o próprio diretório, se for um ponto de montagem). Ser capaz de renomeá-lo seria contraproducente.

O Linux também proíbe rmdirum caminho cujo último componente seja ..(ENOTEMPTY) ou .(EINVAL). O FreeBSD retorna o erro EINVAL para cada um deles. OPadrão POSIX para rmdirtem isso:

A função rmdir() falhará se:
...
[EINVAL] O argumento path contém um último componente que é um ponto.

informação relacionada