Questão Como mover todos os arquivos do diretório atual para o diretório superior?


Como mover todos os arquivos do diretório atual para o diretório superior no linux?

Eu tentei algo como mv *.*, mas não funciona.


125


origem


Eu não tenho representante suficiente para recontar as perguntas, mas posso sugerir [linux] [mv] [cwd] [files]ou algo similar? - Stephan202
Eu refaudei essa questão por solicitação de Stephan202. - eleven81
unix.stackexchange.com/a/251091/139312 - palindrom


Respostas:


O comando que você está procurando é

mv * .[^.]* ..

ou (veja abaixo para mais informações):

(shopt -s dotglob; mv -- * ..)

Explicação: o mv comando move arquivos e diretórios. O último argumento para mv é o alvo (neste caso o diretório um passo "up" na árvore, ..). Os argumentos anteriores são os arquivos e diretórios de origem. O asterisco (*) é um caractere curinga que corresponde a todos os arquivos que não iniciam com um ponto. Arquivos que começam com um ponto (dotfiles) estão "ocultos". Eles são combinados usando o padrão .[^.]* (veja a edição abaixo).

Veja a página de manual que liguei para mais informações sobre mv.


Por quê .[^.]* ao invés de .* ?

Como Chris Johnsen corretamente aponta: o padrão .* também corresponde . e ... Como você não quer (e não pode) movê-los, é melhor usar um padrão que corresponda a qualquer nome de arquivo começando com um ponto exceto aqueles dois. O padrão .[^.]* faz exatamente isso: combina qualquer nome de arquivo (1) começando com um ponto (2) seguido por um caractere que é não um ponto (3) seguido por zero ou mais caracteres arbitrários.

Como Paggas  aponta, também teríamos que adicionar o padrão .??* para corresponder arquivos que começam com dois pontos. Veja a sua resposta para uma solução alternativa usando find.

Arjan responda menções shopt a fim de evitar todos esses problemas com dotfiles. Mas ainda há o problema com os arquivos que começam com um traço. E isso requer três comandos. Ainda assim, gosto da ideia. Eu proponho usá-lo assim:

(shopt -s dotglob; mv -- * ..)

Isso executa shopt em um subshell (assim nenhuma segunda chamada para shopt necessário) e usa -- para que os arquivos que começam com um traço não sejam interpretados como argumentos para mv.


192



Usando .* pode causar mv para produzir avisos / erros sobre não ser capaz de se mover . e ... Você pode tentar mv * .[^.]* .. em vez de. - Chris Johnsen
Resposta muito completa, obrigado.
@alain: de nada, e bem vindo ao site! (Se (e somente se) um dos posts aqui responder a sua pergunta o suficiente, então você pode marcá-lo como tal. Isso fará com que o cartaz tenha 15 pontos extras de reputação, e também lhe dará 2 repetições extras.) - Stephan202
Eu realmente gosto da solução shopt rodando em um subshell :) - Paggas
Não há nenhum dano na sintaxe *. * - incluindo .. só é perigoso quando usado com chmod e chown e o sinalizador "recurse", ou seja, chmod -R ou chown -R. E nesses casos, nunca sempre digite chown. * ou chmod. * - coloque o diretório principal no caminho que você está procurando e use -h (não siga os links simbólicos). Mas, mv .. simplesmente não faz nada, então não se preocupe com isso. - chris


Resposta curta: use

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

Resposta longa:

O comando

mv * .* ..

não vai funcionar desde .* pode combinar . e ... Mas o comando

mv * .[^.]* ..

também não funcionará, já que .[^.]* não corresponde, por exemplo, ..filename! Em vez disso, o que eu faço é

mv * .[^.] .??* ..

que corresponderá a tudo, exceto . e ... * vai combinar tudo o que não começa com um ., .[^.] irá coincidir com todos os nomes de 2 caracteres começando com um ponto, exceto ..e .??* irá corresponder todos os nomes de arquivos começando com um ponto com pelo menos 3 caracteres.

Melhor ainda, você pode usar

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

que evita os feios glob hacks em mv * .[^.] .??* ..!


41



Obrigado :) Eu teria comentado em você postar, mas eu não tenho bastante reputação ainda. - Paggas
Além disso, esqueci de observar a importância de - para que o comando funcione corretamente com nomes de arquivos que começam com um traço. Eu incluí - na minha resposta encontrar embora. Uma resposta mais completa usando globs é "mv - *. [^.]. ?? ..". - Paggas
+1: voltei para adicionar ..?* para o meu comentário, e você já tinha tomado conta disso. - Chris Johnsen
O que pode estar errado com a tentativa de mv ..? Simplesmente não faz nada e não pode fazer nada. Existem outros comandos onde posso faça algo (chmod e chown) mas mv e rm simplesmente não fazem nada. ou .. - chris
Isto dá mv: opção ilegal - t - pal4life


Apenas por uma questão de completude, pode-se também dizer ao shell Bash para incluir arquivos ocultos, usando shopt:

shopt -s dotglob
mv -- * ..
shopt -u dotglob

12



+1. Muito mais limpo. Eu acho que uma ligeira melhora está em ordem, no entanto. Veja a atualização para minha resposta. - Stephan202


O mv não tem a funcionalidade de mover arquivos ocultos ao usar * - então porque não usar copy?

cp -rf . ..

rm -rf *

Não há necessidade de entrar em soluções complexas de "dotglobbing" e de usar comandos find.


8



Atenção Se você está se movendo no mesmo sistema de arquivosNa maior parte dos casos, você realmente não copiou os arquivos, mas apenas atualizou as entradas do diretório sem mover inodes ou contenents de arquivos. Veja até [1]. Com um cp e rm em vez disso, você está realmente copiando tudo. - Hastur


rsync -a --remove-source-files . ..

rsync é uma ferramenta de cópia de arquivos extremamente poderosa, geralmente usada para executar backups e espelhamentos remotos incrementais eficientes.

Com o comando acima, estamos dizendo rsync para copiar o conteúdo de . para dentro ..

O interruptor -a permite a recursão em . subdiretórios e permite algumas outras opções comuns.

O interruptor --remove-source-files diz ao rsync para remover os arquivos de origem após uma cópia bem-sucedida, isto é, ele faz o rsync se comportar de forma semelhante ao mv comando.


6



Um pouco mais de explicação seria legal. - ChrisF
Claro, espero que seja mais claro agora. - mrucci
Observe que --remove-source-files não removerá diretórios (sincronizados). - Dennis
Boa solução aceita me dá -bash: /bin/mv: Argument list too long erro. Este aqui funciona como o encanto. - userlond


Ultimamente tentando mv . falhará porque o mv não poderá desvincular o diretório em que você está. Você poderia mv * .. para mover os arquivos no cwd.


2



Oi obrigado que funcionou!


mv * .??* ../.

* Obtém todos os arquivos não-ponto. .??* fica tudo. arquivos com pelo menos três bytes de comprimento, o que funciona para todos os legítimos. Qualquer coisa que você provavelmente quer rm ao invés de mv de qualquer forma.

o ../. não oferece nenhum benefício direto sobre .. mas ao fazer um movimento para o diretório é um hábito muito bom entrar, porque ele falhará, como você quer, se houver algo errado com o caminho. Por exemplo, mv xyz bletch, onde você pensar  bletch é um diretório, pode ser mais certo com mv xyz bletch/..


2



Você pode adicionar .[^.] para obter arquivos de capa como .a. - Chris Johnsen
Não há diferença entre ../ e ../. então eu não me incomodaria digitando o. depois da barra. Além disso, no caso de mv e rm, não faz mal incluir. e .. na lista, ou seja, não há nada de errado ou assustador com mv *. * / path / to / file /, assim como rm. ou mesmo -rf. não faz nada. - chris


Este comando minimizado funciona na maioria dos shells modernos:

\mv -- {,.{[^.],??}}* ..

Caso contrário, é uma solução portátil:

\mv -- * .[^.] .??* ..

Características:

  1. \ impede aliases de alterar de maneira indesejada.

  2. - evita que nomes de arquivos contendo hífens principais (-xyz) sejam interpretados como argumentos de linha de comando.

  3. . [^.] corresponde a todos os nomes de dois caracteres que começam com. exceto ..

  4. . * corresponde a todos os outros nomes de arquivos com três ou mais caracteres.

Implementações Naive:

  1. O seguinte ignora os nomes de arquivos UNIX ocultos, aqueles que começam com. (.bashrc).

    mv * ..
    
  2. As seguintes correspondências .. que recursivamente tenta mover todos os diretórios eventualmente todo o caminho de volta para / into .. do diretório de trabalho atual ($ PWD ou pwd). Nunca use.

    mv .* ..
    

1