Como copiar com o cp para incluir arquivos e diretórios ocultos e seu conteúdo?

392

Como posso cp -rcopiar absolutamente todos os arquivos e diretórios em um diretório

Requisitos:

  • Inclua arquivos ocultos e diretórios ocultos.
  • Seja um único comando com um sinalizador para incluir o acima.
  • Não é necessário confiar na correspondência de padrões.

Meu feio, mas trabalhando, hack é:

cp -r /etc/skel/* /home/user
cp -r /etc/skel/.[^.]* /home/user

Como posso fazer isso tudo em um comando sem a correspondência de padrões? Qual sinalizador eu preciso usar?

onze81
fonte
1
Mais respostas aqui, embora elas não pareçam tão boas; serverfault.com/questions/3154/…
Roel Van de Paar
Por favor, Eleven81, considere alterar a resposta aceita pela resposta dada por @bruno pereira, porque evita a criação de uma nova pasta. Caso contrário, deixe que esse comentário seja um aviso para os novos leitores para verificar também a outra resposta (mais votada). Tx.
Dr Beco

Respostas:

265

Não especifique os arquivos:

cp -r /etc/skel /home/user

(Observe que ainda /home/usernão deve existir, caso contrário, ele será criado /home/user/skel.)

Randy Orrison
fonte
61
É possível usar algo semelhante, se /home/user/skel não existe?
Bradley.ayers
@ bradley.ayers Acho que é possível copiar para um subdiretório temporário e depois movê-los para o nível superior (já que mover na mesma unidade é rápido). Menos que o ideal, mas mais curto que outras soluções para mim.
Halil Özgür
7
@ bradley.ayers resposta de Bruno abaixo endereços à sua pergunta
Mark
1
Esta solução não funcionou para mim. Não copiou arquivos ocultos. Estou usando o CentOS versão 6.5. A solução de @ Bruno fez o truque.
Technext
2
No ubuntu / debian, isso coloca o diretório 'skel' dentro do diretório de destino e não os arquivos recorrentes dentro do skel. Use -T(sem alvo) abaixo para o uso adequado. ( -rTfor recursivo)
bshea
468

Digamos que você criou a nova pasta (ou vai criar uma) e deseja copiar os arquivos para ela após a criação da pasta

mkdir /home/<new_user>
cp -r /etc/skel/. /home/<new_user>

Isso copiará todos os arquivos / pastas recursivamente de /etc/skelpara a pasta já existente criada na primeira linha.

Bruno Pereira
fonte
5
Se eu não entendi errado, isso não copiava arquivos ocultos / de ponto.
Halil Özgür
34
Funciona bem para mim. Observe que o '.' é fundamental para o seu funcionamento.
Mark
12
Funciona, mas por que? Não foi possível encontrar uma referência a isso no manual.
Julien Palard
5
Eu acho que funciona porque normalmente, isso criaria uma nova pasta com o nome da última pasta no primeiro argumento. No entanto, como esse nome é ., esse comportamento exigiria a criação de um diretório já existente; portanto, apenas pula essa etapa.
Zenexer
28
@Textext O globbing padrão no bash não inclui nomes de arquivos que começam com a ., para alterar que você precisa usar o shopt -s dotglobcomando antes para poder incluir esses arquivos. Portanto *, com , por padrão, você está pedindo para copiar todos os arquivos recursivamente deste diretório que pode ser expandido usando *(o que não inclui arquivos ocultos por padrão). Enquanto do outro lado, .você está usando o cp para copiar recursivamente tudo de "este diretório".
Bruno Pereira
79

O meio correto de fazer isso é usar a -T (--no-target-directory)opção e copiar recursivamente as pastas (sem barras, asteriscos etc.), ou seja:

cp -rT /etc/skel /home/user

Isso copiará o conteúdo de /etc/skelpara /home/user(incluindo arquivos ocultos), criando a pasta /home/userse ela não existir; no entanto, a -Topção impede que o conteúdo /etc/skelseja copiado para uma nova pasta, /home/user/skelcaso ela /home/userexista.

TechnocratiK
fonte
3
Resposta correta. +1
bshea
este foi realmente exatamente a resposta certa
Gaetan
esta é a melhor resposta do grupo; o seu o único que resolve o problema sem complicar-lo
ZaxLofful
exatamente funciona para copiar como esperado
Chetabahana 31/03
Adore quando você usa a bandeira cmd correta para um caso.
Tran Triet
66

bashem si tem uma boa solução, tem um shell option, você pode cp, mve assim por diante .:

shopt -s dotglob # for considering dot files (turn on dot files)

e

shopt -u dotglob # for don't considering dot files (turn off dot files)

A solução acima é padrão de bash

NOTA:

shopt # without argument show status of all shell options
-u # abbrivation of unset 
-s # abbrivation of set
PersianGulf
fonte
2
Isso é útil quando você deseja copiar apenas o conteúdo sem criar um novo diretório dentro do destino. Especialmente quando o diretório de destino é o ponto de montagem.
kaszynek
3
Isso realmente é a melhor resposta e chega ao coração da questão ..
Stephen
7
É setoptpara o zsh, caso alguém esteja se perguntando.
Pat
25

Use rsync:

rsync -rtv source_folder/ destination_folder/

user1084282
fonte
Melhor opção para mim, embora eu use --progress para obter mais feedback sobre todo o processo.
Edenshaw
5

rsync é bom, mas outra opção:

cp -a src/ dst/

Da ajuda principal:

   -a, --archive
          same as -dR --preserve=all

   -d     same as --no-dereference --preserve=links

   -R, -r, --recursive
          copy directories recursively
Wink Saville
fonte
Eu sempre usei cp -r. Obrigado por mencionar cp -a
Pinaki Mukherjee
4

Se o diretório de origem e destino tiver o mesmo nome, mesmo se o diretório de destino existir, você pode simplesmente digitar:

cp -R /etc/skel /home/

Isso copiará o diretório / etc / skel para / home /, incluindo arquivos e diretórios ocultos.

Eventualmente, você pode copiar o diretório e renomeá-lo em uma única linha:

cp -R /etc/skel /home/ && mv /home/skel /home/user
Gabriel Hautclocq
fonte
Ou você pode simplesmente usar cp -r /etc/skel /home/userpara renomear skela user...
David
Isso mesmo, apenas se / home / user ainda não existir.
Gabriel Hautclocq 14/10
4

Você pode usar o rsync.

rsync -aP ./from/dir/ /some/other/directory/

Você pode até copiar sobre ssh

rsync -aP ./from/dir/ username@remotehost:/some/other/directory/

Existem vários sinalizadores que você pode usar: -a, --archive # archive (-rlptgoD)

-r, --recursive
-l, --links      # copy symlinks as links
-p, --perms      # preserve permissions
-t, --times      # preserve times
-g, --group      # preserve group
-o, --owner      # preserve owner
-D               # --devices --specials

--delete         # Delete extra files

You may want to add the -P option to your command.

--partial        # By default, rsync will delete any partially transferred file if the transfer is interrupted. In some circumstances it is more desirable to keep partially transferred files. Using the --partial option tells rsync to keep the partial file which should make a subsequent transfer of the rest of the file much faster.

-P               # The -P option is equivalent to --partial --progress.   Its  purpose  is to make it much easier to specify these two options for a long transfer that may be interrupted.

Página de manual Rsync

RoshP
fonte
4

A maneira mais simples é:

cp -r /etc/skel/{.,}* /home/user

A expressão {.,}*inclui todos os arquivos e diretórios (também começando com um ponto).

Se você não quiser usar a expressão acima, poderá usar a cppropriedade, que é a capacidade de especificar várias fontes para uma pasta de destino:

cp -r /etc/skel/* /etc/skel/.* /home/user
simhumileco
fonte
1
isso perderia arquivos como ..anythingou ...anythingetc. - stackoverflow.com/a/31438355/2351568 contém o regex correto para esse problema. || mas de qualquer maneira usando shopt -s dotglobainda é a melhor solução!
DJCrashdummy
@DJCrashdummy infelizmente, não entendo por que você escreveu sua atenção. Afinal, minha solução leva em consideração os casos sobre os quais você escreve. Considera
simhumileco
desculpe texto errado! - o problema da sua resposta é que ela também considerará .e ..(que é equivalente à pasta atual e à sua pasta). || mas ainda assim a resposta no link explica mais e fornece uma solução.
DJCrashdummy
2

Observe que há um truque da linha de comando (funciona em, pelo menos, sh , bash e ksh ): basta sufixo o diretório from com uma barra. Isso colocará o conteúdo do diretório from no diretório to (ironicamente, eu aprendi sobre esse truque ao usar o rsync ).

Exemplo:

/tmp$ mkdir test_dir1
/tmp$ cd test_dir1/
/tmp/test_dir1$ touch aa
/tmp/test_dir1$ touch .bb
/tmp/test_dir1$ cd ..
/tmp$ mkdir test_dir2

/tmp$ cp -r test_dir1/* test_dir2
/tmp$ ls -1a test_dir2
.
..
aa

/tmp$ cp -r test_dir1/ test_dir2
/tmp$ ls -1a test_dir2
.
..
.bb
aa
Dustin Oprea
fonte
2

Eu vim aqui pesquisando no Google uma solução para o mesmo problema, então percebi que é fácil encontrar a localização. A vantagem não depende do shell ou de utilitários especiais que podem não estar instalados.

find /etc/skel/ -mindepth 1 -exec cp -r {} /home/username/ \;

Eu tentei o truque com barra à direita, mas isso não funcionou para mim.

Linus
fonte
2

Minha solução para esse problema quando tenho que copiar todos os arquivos (incluindo .arquivos) para um diretório de destino mantendo as permissões é: (substituir, se já existir)

yes | cp -rvp /source/directory /destination/directory/

yesé para substituir automaticamente os arquivos de destino, rrecursivo, vdetalhado e preter permissões.

Observe que o caminho de origem não está terminando com um/ (para que todos os arquivos / diretório e. Arquivos sejam copiados)

O diretório de destino termina/ quando colocamos o conteúdo da pasta de origem no destino como um todo.

Rajneesh Gadge
fonte
1

Eu vi que o cp nem sempre copia arquivos ocultos e se você deseja um comando que parece funcionar em todos os dialetos linux / unix, tente usar:

cd /etc/skel
find | cpio -pdumv /home/user
Mikael Nyborg
fonte
-2

Desde pelo menos o K3b 2.0.3, existe uma caixa de perguntas que aparece quando o diretório é adicionado ao projeto, que pergunta se você deseja incluir arquivos ocultos ... há também uma pergunta que aparece para perguntar sobre como incluir links. Coisas legais!

Fred James
fonte
"uma caixa de perguntas que aparece" - para um comando shell (CLI)?
Scott