Como usar o comando 'cp' para excluir um diretório específico?
411
Quero copiar todos os arquivos em um diretório, exceto alguns arquivos em um subdiretório específico. Notei que o comando 'cp' não tinha uma opção --exclude. Então, como posso conseguir isso?
Observe que a opção dir thefoldertoexcludeafter --excludeé relativa a sourcefolder, ie sourcefolder/thefoldertoexclude,.
Além disso, você pode adicionar -npara execução a seco para ver o que será copiado antes de executar a operação real e, se estiver tudo bem, remova-o -nda linha de comando.
Acordado, você não pode bater a simplicidade e poder de--exclude
Matthew Wilcoxson
31
é o thefoldertoexcludeparente sourcefolderou o diretório de trabalho atual? graças
Beebee
46
É relativo à pasta de origem. Isso excluirá a origem da pasta / .git de ser copiada. rsync -r
exclui o
15
Talvez eu esteja errado, mas acho uma boa prática adicionar "opções" antes de "parâmetros". Além disso, a página de manual dos relatórios rsync --exclude utilizável como com a sintaxe "=" ou sem. Portanto, para padronizar os sistemas operacionais, eu usaria rsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder- de qualquer maneira, voto positivo para o rsync, em vez da localização, pois você pode facilmente usar caminhos absolutos para a fonte, enquanto a localização é mais complicada, pois usa {}o dst.
Xavi Montero
1
@mamun É claro exemplo de servidor remoto para máquina local: $ rsync [email protected]:/var/www/mypage /var/www/mylocalpage/ou de local para remoto$ rsync /var/www/mylocalpage/ [email protected]:/var/www/mypage
sobi3ch
84
Bem, se a exclusão de certos padrões de nome de arquivo tivesse que ser executada por todo utilitário de arquivo unix-ish (como cp, mv, rm, tar, rsync, scp, ...), uma imensa duplicação de esforço ocorreria. Em vez disso, essas coisas podem ser feitas como parte do globbing , ou seja, pela sua concha.
Então você coloca um padrão dentro !(), e isso anula a correspondência. O padrão pode ser arbitrariamente complexo, a partir da enumeração de caminhos individuais (como Vanwaril mostra em outra resposta): !(filename1|path2|etc3)para coisas semelhantes a expressões regulares com estrelas e classes de caracteres. Consulte a página de manual para obter detalhes.
Acho que você precisa o -pathargumento para hierarquias de caminho de teste, não -iname
James Murty
3
E você também precisará de um ponto e vírgula no final:find . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
Matthew Wilcoxson 14/02
1
Uau, isso não me permite: "As edições devem ter pelo menos 6 caracteres"!
Matthew Wilcoxson
1
@MatthewWilcoxson Meh. Essas restrições serão levantadas assim que você ganhar um pouco mais de rep. Eu editei a resposta em conformidade. Obrigado novamente!
Linus Kleen
1
@ Henning, por que não rsync? Porque pode não estar presente no sistema! enquanto find, cpestá sempre em seus lugares. Ou você é do tipo de pessoa que instalou 2 galhos de coisas para fazer coisas simples?
Feito uma função shell que simplifica o uso para caminho de origem personalizado e exclusão de apenas um arquivo ou pasta: # $1 = source path # $2 = destination path # $3 = filter copy_from_source_to_destination_except_filter() { cp -r $(ls -A $1 | grep -v -w $3 | awk -v path=$1 '{printf "%s/%s ", path, $1}') $2 }
ElectRocnic
falha com diretórios com espaços
Sérgio
27
A maneira mais fácil que encontrei, onde você pode copiar todos os arquivos, excluindo arquivos e pastas, apenas adicionando seus nomes entre parênteses:
rsyncé realmente bastante complicado. precisa fazer vários testes para fazê-lo funcionar.
Vamos dizer que você deseja copiar /var/www/htmlpara /var/www/devmas necessidade de excluir/var/www/html/site/video/ diretório talvez devido ao seu tamanho. O comando seria:
A última barra /na fonte é necessária; caso contrário, ela também copiará o diretório de origem, em vez de seu conteúdo e se tornará /var/www/dev/html/xxxx, o que talvez não seja o que você deseja.
O --excludecaminho é relativo à fonte diretamente. Mesmo se você colocar o caminho absoluto completo, ele não funcionará.
-vé detalhado, -aé para o modo de arquivo, o que significa que você deseja recursão e deseja preservar quase tudo.
atente para as entradas de diretório que contêm espaços.
Paulo Scardine
3
Esta é uma modificação da resposta de Linus Kleen. Sua resposta não funcionou para mim porque haveria um. adicionado na frente do caminho do arquivo que o cp não gosta (o caminho seria semelhante ao código-fonte / .destination / file).
Talvez não seja bonito - mas esta é a única opção que encontrei aqui que funciona com cpum shell POSIX padrão sh.
tomekwi
1
Esta resposta é dramaticamente subestimada. Essa é a resposta mais compatível, mais fácil de ler e mais fácil de entender. Parabéns, não sei por que não pensei nisso.
Robert Talada
Obrigado @RobertTalada, até onde vai a resposta agora? ️🌈
Eu uso um loop "do while" para ler a saída do comando find. Neste exemplo, estou correspondendo (em vez de excluir) determinados padrões, pois há um número mais limitado de correspondências de padrão que eu quero do que não quero. Você pode reverter a lógica com um -not na frente dos sinalizadores -iname:
Utilizo o acima para copiar todos os arquivos de tipo de música que são mais recentes no meu servidor que os arquivos em um Western Digital TV Live Hub que eu montei em / media / wd. Eu uso o acima exposto porque tenho muitos arquivos de DVD, mpegs etc. que desejo excluir E porque, por algum motivo, o rsync parece estar copiando, mas depois de olhar para o dispositivo wd, os arquivos não estão lá, apesar de não haver erros durante o rsync com este comando:
A primeira parte de lstodos os arquivos, mas oculta arquivos específicos com sinalizador -I. A saída de lsé usada como entrada padrão para a segunda parte. xargsconstruir e executar comando a cp -rf -t destdirpartir da entrada padrão. o sinalizador -rsignifica copiar diretórios recursivamente, -fsignifica copiar arquivos à força que sobrescreverá os arquivos no destdir, -tespecifique o diretório de destino para o qual copiar.
tar -c | tar -x
?Respostas:
O rsync é rápido e fácil:
Você pode usar
--exclude
múltiplos tempos.Observe que a opção dir
thefoldertoexclude
after--exclude
é relativa asourcefolder
, iesourcefolder/thefoldertoexclude
,.Além disso, você pode adicionar
-n
para execução a seco para ver o que será copiado antes de executar a operação real e, se estiver tudo bem, remova-o-n
da linha de comando.fonte
--exclude
thefoldertoexclude
parentesourcefolder
ou o diretório de trabalho atual? graçasrsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder
- de qualquer maneira, voto positivo para o rsync, em vez da localização, pois você pode facilmente usar caminhos absolutos para a fonte, enquanto a localização é mais complicada, pois usa{}
o dst.$ rsync [email protected]:/var/www/mypage /var/www/mylocalpage/
ou de local para remoto$ rsync /var/www/mylocalpage/ [email protected]:/var/www/mypage
Bem, se a exclusão de certos padrões de nome de arquivo tivesse que ser executada por todo utilitário de arquivo unix-ish (como cp, mv, rm, tar, rsync, scp, ...), uma imensa duplicação de esforço ocorreria. Em vez disso, essas coisas podem ser feitas como parte do globbing , ou seja, pela sua concha.
bater
man 1 bash
, / extglob .Exemplo:
Então você coloca um padrão dentro
!()
, e isso anula a correspondência. O padrão pode ser arbitrariamente complexo, a partir da enumeração de caminhos individuais (como Vanwaril mostra em outra resposta):!(filename1|path2|etc3)
para coisas semelhantes a expressões regulares com estrelas e classes de caracteres. Consulte a página de manual para obter detalhes.zsh
man 1 zshexpn
, / geração de nome de arquivo .Você pode fazer
setopt KSH_GLOB
e usar padrões semelhantes ao bash. Ou,Então
x~y
corresponde ao padrãox
, mas exclui o padrãoy
. Mais uma vez, para obter detalhes completos, consulte a página de manual.peixe novo!
A casca do peixe tem uma resposta muito mais bonita para isso:
Dica profissional de bônus
Digite
cp *
, clique CtrlX*e veja o que acontece. não é prejudicial eu prometofonte
zsh
embora.setopt -u extglob
.Por que usar
rsync
quando você pode fazer:Isso pressupõe que a estrutura de diretórios de destino seja igual à da origem.
fonte
-path
argumento para hierarquias de caminho de teste, não -inamefind . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
rsync
? Porque pode não estar presente no sistema! enquantofind
,cp
está sempre em seus lugares. Ou você é do tipo de pessoa que instalou 2 galhos de coisas para fazer coisas simples?fonte
# $1 = source path # $2 = destination path # $3 = filter copy_from_source_to_destination_except_filter() { cp -r $(ls -A $1 | grep -v -w $3 | awk -v path=$1 '{printf "%s/%s ", path, $1}') $2 }
A maneira mais fácil que encontrei, onde você pode copiar todos os arquivos, excluindo arquivos e pastas, apenas adicionando seus nomes entre parênteses:
fonte
-bash: !: event not found
Expandindo o comentário do mvds , isso funciona para mim
fonte
É relativo ao diretório de origem.
Isso excluirá o diretório
source/.git
de ser copiado.fonte
rsync
e primeiro tente com a opção -n para ver o que será copiado
fonte
Presumo que você esteja usando bash ou dash. Isso funcionaria?
Fazendo um ls excluindo os arquivos que você não deseja e usando isso como o primeiro argumento para cp
fonte
ls
e simplesmente fazercp !(file1|file1) dest
.cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
Outra opção mais simples é instalar e usar o rsync, que possui uma opção --exclude-dir e pode ser usado para arquivos locais e remotos.
fonte
rsync
é realmente bastante complicado. precisa fazer vários testes para fazê-lo funcionar.Vamos dizer que você deseja copiar
/var/www/html
para/var/www/dev
mas necessidade de excluir/var/www/html/site/video/
diretório talvez devido ao seu tamanho. O comando seria:rsync -av --exclude 'sites/video' /var/www/html/ /var/www/dev
Alguma ressalva :
/
na fonte é necessária; caso contrário, ela também copiará o diretório de origem, em vez de seu conteúdo e se tornará/var/www/dev/html/xxxx
, o que talvez não seja o que você deseja.O
--exclude
caminho é relativo à fonte diretamente. Mesmo se você colocar o caminho absoluto completo, ele não funcionará.-v
é detalhado,-a
é para o modo de arquivo, o que significa que você deseja recursão e deseja preservar quase tudo.fonte
Editar: esqueceu de excluir também o caminho de destino (caso contrário, ele copiaria recursivamente).
fonte
Esta é uma modificação da resposta de Linus Kleen. Sua resposta não funcionou para mim porque haveria um. adicionado na frente do caminho do arquivo que o cp não gosta (o caminho seria semelhante ao código-fonte / .destination / file).
Este comando funcionou para mim:
find . -type f -not -path '*/exlude-path/*' -exec cp --parents '{}' '/destination/' \;
o comando --parents preserva a estrutura de diretórios.
fonte
Apenas mova-o temporariamente para um diretório oculto (e renomeie-o depois, se desejado).
fonte
cp
um shell POSIX padrãosh
.fonte
Eu uso um loop "do while" para ler a saída do comando find. Neste exemplo, estou correspondendo (em vez de excluir) determinados padrões, pois há um número mais limitado de correspondências de padrão que eu quero do que não quero. Você pode reverter a lógica com um -not na frente dos sinalizadores -iname:
Utilizo o acima para copiar todos os arquivos de tipo de música que são mais recentes no meu servidor que os arquivos em um Western Digital TV Live Hub que eu montei em / media / wd. Eu uso o acima exposto porque tenho muitos arquivos de DVD, mpegs etc. que desejo excluir E porque, por algum motivo, o rsync parece estar copiando, mas depois de olhar para o dispositivo wd, os arquivos não estão lá, apesar de não haver erros durante o rsync com este comando:
fonte
A primeira parte de
ls
todos os arquivos, mas oculta arquivos específicos com sinalizador-I
. A saída dels
é usada como entrada padrão para a segunda parte.xargs
construir e executar comando acp -rf -t destdir
partir da entrada padrão. o sinalizador-r
significa copiar diretórios recursivamente,-f
significa copiar arquivos à força que sobrescreverá os arquivos nodestdir
,-t
especifique o diretório de destino para o qual copiar.fonte
cp -r
ls -A | grep -v "Excluded_File_or_folder"
../$target_location -vfonte