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

133

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.

Jens Erat
fonte
Não tenho representante suficiente para remarcar perguntas, mas posso sugerir [linux] [mv] [cwd] [files]algo parecido?
21420
Marquei esta pergunta de novo com o pedido de Stephan202.
28/11

Respostas:

202

O comando que você está procurando é

mv * .[^.]* ..

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

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

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

Veja a página de manual que eu vinculei para obter mais informações mv.


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

Como Chris Johnsen aponta corretamente: o padrão .*também combina com .e ... Como você não deseja (e não pode) movê-los, é melhor usar um padrão que corresponda a qualquer nome de arquivo que comece com um ponto, exceto os dois . O padrão .[^.]*faz exatamente isso: ele corresponde a 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 aos arquivos começando com dois pontos. Veja a resposta dele para uma solução alternativa usando find.

A resposta de Arjan menciona shoptpara evitar todos esses problemas com os dotfiles. Mas ainda há o problema com os arquivos que começam com um traço. E isso requer três comandos. Ainda assim, eu gosto da ideia. Proponho usá-lo assim:

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

Isso é executado shoptem um subshell (portanto, não é shoptnecessária uma segunda chamada ) e é usado --para que os arquivos que começam com um hífen não sejam interpretados como argumentos para mv.

Stephan202
fonte
7
O uso .*pode fazer com que o mv produz avisos / erros sobre não poder se mover .e ... Você pode tentar mv * .[^.]* ...
31720 Chris Johnsen
11
@ alain: de nada, e bem-vindo ao site! (Se (e somente se) uma das postagens aqui responder suficientemente à sua pergunta, você poderá marcá-la como tal. Isso obterá o pôster com 15 pontos de reputação extras e também lhe dará 2 repetições extras.)
Stephan202
Eu realmente gosto da solução shopt sendo executado em um subshell :)
Paggas
2
Não há nenhum dano na sintaxe *. * - incluindo .. é apenas perigoso quando usado com chmod e chown e a flag "recurse", ou seja, chmod -R ou chown -R. E nesses casos, nunca digite chown. * Ou chmod. * - escolha o diretório superior 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.
chris
11
Os três padrões corretos são *, .[^.]*e ..?*. O segundo talvez .[!.]*para conchas mais antigas (POSIX). Também leia
42

Resposta curta: use

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

Resposta longa:

O comando

mv * .* ..

não funcionará, pois .*pode corresponder .e ... Mas o comando

mv * .[^.]* ..

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

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

que combinará com tudo, exceto .e ... *corresponderá a tudo que não começa com a ., .[^.]corresponderá a todos os nomes de arquivos de 2 caracteres começando com um ponto .., exceto , e .??*corresponderá a todos os nomes de arquivos iniciados 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 hacks da glob mv * .[^.] .??* ..!

Paggas
fonte
11
Além disso, esqueci de observar a importância de - para que o comando funcione corretamente com nomes de arquivos começando com um traço. Eu incluí - na minha resposta encontrar. Uma resposta mais completa usando globs é "mv - *. [^.]. ?? * ..".
Paggas 28/10/09
+1: voltei para adicionar ..?*ao meu comentário e você já cuidou dele.
31420 Chris Johnsen
11
O que pode estar errado com a tentativa de mv ..? Simplesmente não faz nada e não pode fazer nada. Existem outros comandos nos quais ele pode fazer algo (chmod e chown), mas mv e rm simplesmente não fazem nada. ou ..
chris
11
Isso dá mv: opção ilegal - t
pal4life
11
Além disso, o traço duplo indica mvpara parar de procurar outras opções de comando. Os chavetas são um nome de arquivo resultante. O sinal de adição diz que, em vez de executar o exec por resultado (ou seja, por nome de arquivo), coloque o máximo de resultados em um único exec possível. Para ser completo, -t..é importante mover o destino de destino para o qual mover todos esses arquivos.
Isuldor
14

Apenas por questões de integridade, também é possível dizer ao shell do Bash para incluir arquivos ocultos, usando shopt:

shopt -s dotglob
mv -- * ..
shopt -u dotglob
Arjan
fonte
+1. Muito mais limpo. Eu acho que uma ligeira melhoria está em ordem, no entanto. Veja a atualização para minha resposta.
Stephan202
8

O mv não possui a funcionalidade de mover arquivos ocultos ao usar *- então, por que não usar cópia?

cp -rf . ..

rm -rf *

Não é necessário entrar em soluções complexas de uso de dotglobbing e usando os comandos find.

Micky Martin
fonte
Aviso Se você estiver movendo no mesmo sistema de arquivos , na maior parte dos casos, você realmente não copiou os arquivos, mas apenas atualiza as entradas do diretório sem mover o inode ou o conteúdo do arquivo. Veja até [1 ]. Com um cpe, em rmvez disso, você está realmente copiando tudo.
Hastur 22/01
6
rsync -a --remove-source-files . ..

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

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

A opção -aativa a recursão em .subdiretórios e outras opções comuns.

O switch --remove-source-filesdiz ao rsync para remover os arquivos de origem após uma cópia bem-sucedida, ou seja, faz com que o rsync se comporte de maneira semelhante ao mvcomando.

mrucci
fonte
11
Um pouco mais de explicação seria legal.
ChrisF
Claro, espero que esteja mais claro agora.
mrucci
Observe que --remove-source-filesnão removerá diretórios (sincronizados).
Dennis
Solução agradável e aceita me dá -bash: /bin/mv: Argument list too longerro. Este funciona como o charme.
userlond
2

Por fim, tentar mv .falhará porque o mv não poderá desvincular o diretório em que você está atualmente. Você pode mv * ..mover os arquivos no cwd.

DaveParillo
fonte
2
mv * .??* ../.

*obtém todos os arquivos que não são pontos. .??*recebe tudo. arquivos com pelo menos três bytes, o que funciona para todos os legítimos. Provavelmente, qualquer coisa que você queira é rmmelhor que antes mv.

O ../.recurso não oferece nenhum benefício direto, ..mas, ao fazer uma mudança para o diretório, é um hábito muito bom entrar, porque ele falhará, como você deseja, se houver algo errado com o caminho. Por exemplo, mv xyz bletchonde você acha que bletch é um diretório, você pode ter mais certeza mv xyz bletch/..

DigitalRoss
fonte
2
Você pode adicionar .[^.]para obter arquivos de capa como .a.
31420 Chris Johnsen
Não há diferença entre ../ e ../. então eu não me incomodaria em digitar 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 assustador ou errado com mv *. * / path / to / file /, assim como rm. ou mesmo -rf. não faz nada.
chris
2

Este comando minimizado funciona na maioria dos shells modernos:

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

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

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

Recursos:

  1. \ evita que aliases alterem mv indesejadamente.

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

  3. . [^.] corresponde aos dois nomes de arquivos de caracteres que começam com. exceto ..

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

Implementações ingênuas:

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

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

    mv .* ..
    
dhchdhd
fonte
2

É mais correto usar o padrão do * .[!.] .??*que, * .[^.] .??*já que o primeiro também funcionará com shells mais antigos, como o ksh88:

mv -- * .[!.] .??* ..
  • -- evita problemas quando você tem um nome de arquivo que começa com -
  • * corresponde a todos os nomes de arquivos que não começam com um .
  • não há nomes de arquivo de um caractere que começam com um .que você pode / deve mover
  • .[!.] corresponde a todos os dois nomes de arquivo de caracteres que começam com um .
  • .??* corresponde a todos os nomes de arquivos de três caracteres (ou mais) que começam com um .

Com o ksh88, o padrão do nome do arquivo de .[^.]fato corresponderá aos nomes dos arquivos ..(que sempre existem) e .^(que provavelmente não existem), tendo um efeito oposto ao desejado.

jrw32982
fonte
0

Encontre e grep também funciona. Esse tipo de estrutura pode ser útil se você quiser selecionar arquivos com critérios mais complicados, modificando find e egrep.

find -maxdepth 1 | egrep '^./.'         # Returns all files

mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..
user3192145
fonte
0

Eu acho que a solução mais fácil para mover todos os arquivos para o diretório pai. seria

mv "`ls`" ../

ou, se houver arquivos / diretórios ocultos

usar:

mv "`ls -a`" ../ 2>/dev/null

Além disso, digamos que você queira mover o conteúdo de alguma pasta para uma de suas pastas internas tony (digamos)

usar:

mv "`ls -a`" /tony 2>/dev/null

Nota:

"`ls -a`" 

Para mover os arquivos que possuem espaços.

2>/dev/null

É para suprimir o aviso / erro porque ls -airia imprimir o .e ..pasta tão bem e você não pode mover ou copiá-los. Portanto, para essas pastas, será exibido um erro (se não usarmos 2> / dev / null) que não será possível movê-las e o restante será movido confortavelmente.

Melhor evitar ls -ase não houver arquivos ocultos e apenas usar ls.

Prabhat Kumar Singh
fonte
Você já tentou o que acontecerá quando correr mv $(ls -a)? Isso tocaria no diretório atual e no diretório abaixo dele, porque ls -aserá exibido ..também.
Sami Laine
Obrigado, @SamiLaine, pela sugestão que fiz nas correções. Mas mv ls -a ../também teria funcionado conforme a necessidade. Sim, ele mostrará os erros como mencionei acima, mas, além disso, ele moverá as pastas / arquivos necessários para o diretório pai.
Prabhat Kumar Singh
Isso não funcionará para arquivos com espaços.
Kenorb 27/05
@kenorb, você precisa aspas duplas no lscomando para mover arquivos com espaços. Fiz as alterações necessárias. Obrigado por apontar.
Prabhat Kumar Singh