Como copiar alguns arquivos, mas não todos?

54

Portanto, você pode usar o *como curinga para todos os arquivos ao usar cpno contexto de um diretório. Existe uma maneira de copiar todos os arquivos, exceto o xarquivo?

Chad Harrison
fonte

Respostas:

42

Em bashvocê pode usar extglob:

 $ shopt -s extglob  # to enable extglob
 $ cp !(b*) new_dir/

onde !(b*)excluir todos os b*arquivos.

Mais tarde, você pode desativar extglobcom

 $ shopt -u extglob
pressa
fonte
Você sabe se há algo equivalente para o shell tcsh?
Levon
Infelizmente eu não. Parece que findé a única maneira de tcsh:find . -maxdepth 1 ! -name "exclude*" -exec cp -t destination {} \+
rush
50

O Rsync lida com isso muito bem.

Exemplo de copiar tudo: rsync -aP /folder1/* /folder/2

Exemplo de cópia de todos com exclusão: rsync -aP --exclude=x /folder1/* /folder2/

O -aPinterruptor:

a: Semelhante a cp -a, recursivo etc. P: Mostra o progresso, um bom recurso do rsync.

Tim
fonte
5
E veja esta resposta para um pequeno guia de listas comuns de exclusão de rsync.
Gilles 'SO- stop be evil'
11
No darwin / MacOS, use em -rPvez de, -aPse quiser recursar. -aé para arquivamento. Não tenho certeza se isso mudou ou se é apenas diferente no MacOS.
Jspoveda
rsynctem a opção de torná-lo recursivo. Exemplo: rsync --recursive -P --exclude=x /folder1/* /folder2/. (Testado apenas no Ubuntu)
n1k31t4
12

Isso não é um recurso cp, é um recurso do seu shell (ele expande *todos os arquivos que não são pontos), então a resposta depende de qual shell você está usando. Por exemplo, zshsuporta esta sintaxe:

$ cp ^x /path/to/destination

Onde ^xsignifica "todos os arquivos, exceto x"

Você também pode combinar padrões de seleção e desmarcação, por exemplo, para copiar todos os arquivos wav, exceto aqueles que contêm xyz, você pode usar:

cp *.wav~*xyz*
Michael Mrozek
fonte
Algum comentário sobre bash?
Chad Harrison
@hydroparadise Eu não sei muito sobre bash, mas esta resposta parece cobri-lo
Michael Mrozek
E o tcsh? Ninguem sabe?
Levon
4

Também pode ser feito no shell bourne antigo (portátil / compatível) de várias maneiras, com ferramentas padrão de maneira muito menos elegante do que usar globbing avançado do shell ou comandos com opções de exclusão incorporadas.

Se não houver muitos arquivos (e não com nomes, incluindo espaços e / ou quebras de linha), isso pode ser uma maneira:

cp `ls | egrep -v '^excludename$'` destdir/.

Claro, as bashferramentas GNU são ótimas e poderosas, mas nem sempre estão disponíveis. Se você pretende colocá-lo em um script portátil, eu recomendaria findcomo no comentário de Rush.

MattBianco
fonte
2
Acho que a última parte da sua resposta apenas distrai o tópico em questão. Além disso, "Unix" não é mais o padrão-ouro (se é que alguma vez foi). Só não é relevante se algo é "Unix" ou não é mais, apesar do título deste site ser "Unix e Linux".
27412 Alexander Alexander
2
ESTÁ BEM. Mudei o comentário para aqui: o Unix não é GNU. Concordo que a "unicidade" das coisas não é muito interessante, mas ainda acredito na portabilidade e em conhecer um pouco da sua história.
Matt Bianco
Concordo plenamente com você lá.
27412 Alexander Alexander
2

Se você deseja copiar tudo em uma pasta (incluindo subpastas) para um subdiretório específico:

cp -R $(ls | grep -v '^subdir$') subdir/

Funciona com sh, bash, zsh (pelo menos).

user2707671
fonte
11
Convença-me de que esta não é a mesma intenção quecp -R * subdir/
roaima 28/10
11
Se você usar esse comando "cp -R * subdir /", o bash / zsh tentou copiar 'subdir' de forma recorrente. Você acaba com um erro: "nome muito longo (não copiado)".
user2707671
Bom ponto. Sua sugestão tenta evitar o aviso de cp(não de bash/ sh), " cp: cannot copy a directory, ‘subdir’, into itself, ‘subdir/subdir’". A cópia é concluída corretamente, no entanto. Infelizmente, sua variante quebra com qualquer nome de arquivo que contenha um espaço ou pontuação sensível a shell. Veja unix.stackexchange.com/q/128985/135943
roaima
-1

extglob é a melhor maneira até agora, eu acho.

Outra maneira é usar cp $(ls --ignore=x) subdir/

Edwin Lee
fonte
Isso será interrompido devido a qualquer forma de caracteres especiais nos nomes dos arquivos. (Espaços, novas linhas, $etc.) Nunca analise a saída de ls. unix.stackexchange.com/q/128985/135943
curinga