Mover todos os arquivos, exceto um

155

Como posso mover todos os arquivos, exceto um? Estou procurando algo como:

'mv ~/Linux/Old/!Tux.png ~/Linux/New/'

onde movo coisas antigas para novas - pasta, exceto Tux.png. ! -sign representa uma negação. Existe alguma ferramenta para o trabalho?

Léo Léopold Hertz 준영
fonte

Respostas:

142

Se você usa o bash e tem a extglobopção de shell definida (que geralmente é o caso):

mv ~/Linux/Old/!(Tux.png) ~/Linux/New/
sth
fonte
1
Eu entendi algo errado quando testei o comando para muitos itens: mv ~ / Linux / Old /! (Tux.png Tux1.png Tux2.png) ~ / Linux / New / Esvazia todo o diretório antigo. O que está errado?
Léo Léopold Hertz # 22/09
5
@UnixBasics, tente: ~ / Linux / Old /! (Tux.png | Tux1.png | Tux2.png)
Juliano
@ Juliano Comando muito legal! Existem mais operações matemáticas como OR e XOR? Presumo que um pipe seja para AND.
Léo Léopold Hertz # 22/09
@UnixBasis, sim. Dê uma olhada em gnu.org/software/bash/manual/html_node/Pattern-Matching.html
Juliano
@ Juliano Estou um pouco confuso com os padrões como: mv ~ / Linux /? (Tux * .png) ~ / Linux / Novo / mv ~ / Linux / + (Tux * .png) ~ / Linux / New / No primeiro , Eu queria mover 0-1 Tux -photo. Neste último, eu queria mover fotos 1-n Tux. Eles mudaram tudo. Por quê? É possível mover uma quantidade específica de fotos?
Léo Léopold Hertz # 22/09
97

Coloque o seguinte em seu arquivo .bashrc

shopt -s extglob

Estende regexes. Você pode mover todos os arquivos, exceto um por

mv !(fileOne) ~/path/newFolder

Exceções em relação a outros comandos

Observe que, nos diretórios de cópia, o forward-flash não pode ser usado no nome conforme observado no encadeamento Por que extglob, exceto quebrar, exceto a condição? :

cp -r !(Backups.backupdb) /home/masi/Documents/

isso Backups.backupdb/está errado aqui antes da negação e eu não o usaria nem na movimentação de diretórios por causa do risco de usar incorretamente, depois globs com outros comandos e possíveis outras exceções.

Léo Léopold Hertz 준영
fonte
3
Esta é realmente a resposta correta. O meu estava totalmente errado; felizmente eu o havia usado em uma pasta com apenas alguns arquivos. Aqui estão mais informações sobre o método que Masi mostra: wiki.bash-hackers.org/syntax/pattern Vá para "Linguagem de Padrão Estendido" e você encontrará mais informações sobre isso. Agradecemos a @ paul-whittaker por apontar o problema.
mimoralea
Esta é uma resposta antiga, mas ainda é válida. Estou usando o Ubuntu 18 e o extglob parece estar ativado por padrão (não o comprei). Usei o seguinte comando para mover todos os arquivos no diretório atual para um arquivo que também esteja dentro deste diretório, NÃO incluindo outras pastas de arquivo: mv !(arc*) archive_190629b
TonyG
70

Eu usaria a maneira tradicional do find & xargs:

find ~/Linux/Old -maxdepth 1 -mindepth 1 -not -name Tux.png -print0 | 
    xargs -0 mv -t ~/Linux/New

-maxdepth 1faz com que não procure recursivamente. Se você se importa apenas com arquivos, pode dizer -type f. -mindepth 1faz com que não inclua o ~/Linux/Oldpróprio caminho no resultado. Funciona com qualquer nome de arquivo, incluindo aqueles que contêm novas linhas incorporadas.

Um comentário observa que a -topção mv é provavelmente uma extensão GNU. Para sistemas que não possuem

find ~/Linux/Old -maxdepth 1 -mindepth 1 -not -name Tux.png \
    -exec mv '{}' ~/Linux/New \;
Johannes Schaub - litb
fonte
1
Voto a favor, pois incentiva o aprendizado de uma ferramenta poderosa, encontre. Observe que, para arquivos com espaço em branco, isso não funcionará. Considere "find -print0 | xargs -0" ou então renuncie ao xargs: "encontre [o que você disse] -exec mv -t {} ~ / Linux / New \;"
21477 JasonSmith
Se o seu comando mv não tiver a opção -t, use "find ... -exec mv {} Linux / New \;" ou "encontre ... | xargs -I {} mv {} Linux / Novo". A opção -t parece ser uma extensão GNU, o que é bom para Linux, mas provavelmente não em outro lugar.
Rob Kennedy
jhs, oh eu falhei. De alguma forma, pensei que xargs se dividissem em novas linhas, mas não em espaços. Parece que eu confundido com "ler" :) doente corrigi-lo
Johannes Schaub - litb
Muito obrigado pela dica incrível! Eu ia escolher sth porque ele tem como alvo a questão. No entanto, posso sentir a utilidade de seus comandos mais tarde, então devo escolher o modo "find and xargs". Apenas balança. Obrigado :)
Léo Léopold Hertz 준영 26/03/09
Caminho para complicado. Masi resposta é mais completo, mais fácil e por isso mais correto
user637338
30

Uma maneira rápida seria modificar o nome do arquivo tux para que seu comando de movimento não corresponda.

Por exemplo:

mv Tux.png .Tux.png

mv * ~/somefolder

mv .Tux.png Tux.png
John T
fonte
não use " . ", pois isso moverá apenas arquivos com "." no nome. Apenas "*" é suficiente.
Juliano
1
Se você alterá-lo para *, ele também removerá o arquivo renomeado.
John T
6
@ John T: Não, o * glob não corresponde aos arquivos que começam com ponto.
Bill Karwin
Esta é a melhor resposta de longe. Não há necessidade de alterar ou comentar esta resposta. 100 pontos. Muito obrigada. Bem feito!
Steve K
23

Eu acho que a maneira mais fácil de fazer é com backticks

mv `ls -1 ~/Linux/Old/ | grep -v Tux.png` ~/Linux/New/

Editar:

Use barra invertida com ls para evitar usá-lo com alias, ou seja, principalmente ls é alias como ls --color.

mv `\ls -1 ~/Linux/Old/ | grep -v Tux.png` ~/Linux/New/

Obrigado @Arnold Roa

Rohail Abbas
fonte
1
Você pode explicar por que você usa grep -vlá?
Léo Léopold Hertz # 23/16
1
A opção -v no grep exclui o resultado, é como pegar tudo, exceto o Tux.png
Rohail Abbas
1
Isso certamente é intuitivo, mas as respostas acima são melhores. Se você estiver escrevendo um script, por exemplo, isso exigiria que você estivesse no diretório correto ..
nJGL
@nJGL Nós também podemos dar um caminho absoluto aqui, eu usei o homedirectory (~) já que a pergunta tinha isso
Rohail Abbas
@RohailAbbas Fair suficiente. ✌️
nJGL 13/07
14

Para o bash, a resposta sth está correta. Aqui está a sintaxe zsh (meu shell de escolha):

mv ~/Linux/Old/^Tux.png ~/Linux/New/

Requer a EXTENDED_GLOBopção de shell a ser definida.

Juliano
fonte
3
E se quisermos excluir dois arquivos?
MPEN
13

Acho que isso é um pouco mais seguro e fácil de usar para movimentos simples que excluem determinados arquivos ou diretórios.

ls -1 | grep -v ^$EXCLUDE | xargs -I{} mv {} $TARGET
alex.pilon
fonte
Esta é a melhor solução para o Busybox / ASH
Stuart Cardall
1
Isso funcionou para mim na situação em que eu tinha que mover todos os arquivos, exceto algumas pastas para outra pasta
Umar Hayat
A -lopção para lsincluir muitas informações irrelevantes na linha de comando e resultar em falha do comando mv.
jdhao
5

O seguinte não é um método 100% garantido e não deve ser tentado de forma alguma para scripts. Mas algumas vezes é bom o suficiente para o uso rápido do shell interativo. Um arquivo de arquivo glob como

[abc]*

(que corresponderá a todos os arquivos com nomes começando com a, b ou c) pode ser negado inserindo-se primeiro um caractere "^", ou seja,

[^abc]*

Às vezes eu uso isso para não corresponder ao diretório "lost + found", como por exemplo:

mv /mnt/usbdisk/[^l]* /home/user/stuff/.

Claro que, se houver outros arquivos começando com l, tenho que processá-los posteriormente.

hlovdal
fonte
4
mv `find Linux/Old '!' -type d | fgrep -v Tux.png` Linux/New

O comando find lista todos os arquivos regulares e o comando fgrep filtra qualquer arquivo Tux.png. Os backticks dizem ao mv para mover a lista de arquivos resultante.

David Norman
fonte
4
Nunca, jamais, avalie find como argumentos para outro comando. Coisas ruins vão acontecer. Você pode ter acabado de criar uma vulnerabilidade. Sempre use o comando find -print0 | xargs -0 construa ou encontre -exec.
Juliano
3

Que tal mover tudo na pasta e depois mover o Tux.png de volta?

Não consigo pensar em nenhuma sintaxe do shell para dizer "tudo, exceto ..." de imediato.

David Z
fonte
3
ls ~/Linux/Old/ | grep -v Tux.png | xargs -i {} mv ~/Linux/New/'
aitor
fonte
1
Este comando parece estar faltando uma parte e não funciona no meu computador. ls ~/Linux/Old/ | grep -v Tux.png | xargs -I{} mv {} ~/Linux/New/funciona em vez disso.
Katherine Chen
3

E se:

mv $(echo * | sed s:Tux.png::g) ~/Linux/New/

Você precisa estar na pasta.

antibus
fonte
3

Pode-se pular o grep assim:

ls ~/Linux/Old/ -QI Tux.png | xargs -I{} mv ~/Linux/Old/{} ~/Linux/New/
Arch Linux Tux
fonte
1

Isso poderia ser mais simples e fácil de lembrar e funciona para mim.

mv $(ls ~/folder | grep -v ~/folder/exclude.png) ~/destination

Pakpoom Tiwakornkit
fonte