Copie o conteúdo do diretório usando o comando 'cp'

33

Como você copia todo o conteúdo de um diretório para outro?

Por exemplo:

$ cd /home/newuser
$ cp -a /backup/olduser/* .

O problema com o exposto acima é que o padrão de globing '*' corresponde aos diretórios ocultos '.' e '..' e você acaba com um diretório 'olduser' dentro de 'newuser', além do conteúdo.

Você também pode fazer algo assim:

$ rmdir /home/newuser
$ cp -a /backup/olduser /home/newuser

Mas e se newuser já contiver alguns arquivos e diretórios padrão?

Qual é a maneira mais simples, correta, mais fácil de lembrar e não bagunça de mover o conteúdo de um diretório para outro usando apenas o comando básico 'cp' e o shell?

Der Hochstapler
fonte

Respostas:

31

Experimentar:

cp -ra /backup/olduser/. /home/newuser
Nagul
fonte
Isso é ótimo, mas não consigo descobrir exatamente como isso funciona. Eu acho que é provavelmente porque eu não entendo como .e ..trabalho. Gostaria de explicar?
Bradley.ayers
Isso funcionou para mim, mas cp -r ./a bnão funcionou. Alguma idéia do porquê?
Brig
3
funciona para mim também, mas a ropção não é necessária. A aopção implica r.
MountainX
1
o parâmetro -r parece ser um pouco redundante neste momento!
Master of Celebration
O -aparâmetro não faz nada para ajudar nessa situação. O comando cp -r ./a/. birá copiar o conteúdo, e apenas o conteúdo, de diretório aem diretório b. A -abandeira preserva links, timestamps etc., que não são relevantes para a pergunta.
Steen Schütt 23/10
23

Dois diretórios a e b.

Ambos têm arquivos.

Você está em um diretório que contém a e b.

cp -r ./a b

-r = recursivamente.

Rich Bradshaw
fonte
Você não quer que -a obtenha todos os arquivos?
BW
7
O argumento -a não tem nada a ver com todos os arquivos, é abreviação de archive, preservará a propriedade, as permissões, os tempos de acesso etc. O argumento -a (embora seja muito útil) não é uma opção padrão, e várias implementações de cp não forneça isso.
theotherreceive
1
@mch: incluído automaticamente, porque você pediu cppara copiar um diretório ae a/.somedotfileestá contido em a. se bexistir, este comando criará uma cópia exata de aem b/a.
quack quixote
2
cp -R /some/dir/* /another/dir
Maneira
1
Isto copia um / foo para b / a / foo em vez de para b / foo
Sparr
19

Lembre-se de que, por padrão, cpcopia o primeiro diretório para o segundo diretório, se o segundo existir.

Por exemplo cp -r a b, copiará o diretório a para b. Se bnão existir, ele será criado com o conteúdo de a.

Se você deseja copiar o conteúdo de apara b(por exemplo, ao copiar um sistema de arquivos inteiro em um ponto de montagem), use:

cp -r a/. b

como na resposta anterior.

Observe também que -a, usado em algumas das outras respostas, é o mesmo que -dr --preserve=allpreservará registros de data e hora, contexto e atributos estendidos.

Nicolas Bonnefon
fonte
Como funciona o /.trabalho?
Bradley.ayers
a/.representa o conteúdo do diretório 'a' em oposição ao próprio diretório; na maioria das situações, é sinônimo, mas ao usá- cp -rlo, evita o comportamento padrão do cp (copiar um INTO b).
Nicolas Bonnefon
dica incrível, é exatamente isso que eu estava procurando, mas não encontrei em nenhum outro lugar - tudo o que 'foo / *' ou '-r foo /' falha nos casos de canto.
Tener
@TimoHuovinen '.' não é um curinga. É literalmente o diretório "pai" e '..' é o avô. Isso significa '/foo/./././././.' é o mesmo diretório que '/ foo' e '/ foo / bar / ..' é o mesmo diretório que '/ foo'. Pense neles como hardlinks embutidos no sistema de arquivos.
quuxman
@quuxman obrigado, eu não estava ciente disso naquela época. Vou remover meu antigo comentário para evitar confundir as pessoas.
Timo Huovinen
6

A menos que você tenha reconfigurado seriamente seu shell, o padrão globbing '*' não corresponde '.' ou '..', como você pode verificar usando apenas eco *. O que ele faz é omitir arquivos cujo nome começa com um '.', Para que sua abordagem perca todos os arquivos ocultos. Você pode ajustar parte desse comportamento com as opções de shell, por exemplo, a opção dotglob no bash, mas não será a opção portátil e robusta que você está procurando.

Se você precisar fazer isso mais de uma ou duas vezes, recomendo que você analise o rsync ou o unison (dependendo das necessidades específicas) com especificações de origem e destino cuidadosamente criadas.

Outra alternativa é colocar o diretório de origem em um tarball e descompactá-lo sobre o diretório de destino existente.

Peter Eisentraut
fonte
1
Eu uso isso: ( cd /src/dir ; tar cf - . ) | ( cd /dest/dir ; tar xf - )... o tar cf - .tar é o diretório de origem, incluindo os dotfiles e o cospe no STDOUT, que é canalizado para o STDIN do tar xf -.
quack quixote
Acho que o ponto principal do OP é como fazer referência a arquivos que começam com '.' mas não o especial '.' e diretórios '..'. Existe uma solução muito mais elegante acima, em vez de usar o rsync ou algum outro programa complexo.
quuxman
2

Isso copiará os arquivos normais e ocultos, excluindo o diretório pai ( ..):

cd /directory/to/copy
cp -r * .[^.]* /destination/directory

Se você não excluir o diretório pai, também receberá todo o conteúdo do ..diretório de destino.

mch
fonte
1
Mas isso ainda exclui nomes que começam com .. (por exemplo, ...ou ..super-hidden).
Scott
0

Para copiar arquivos que começam com um ponto, basta cp. * Target /

O mais fácil é executar o comando cp duas vezes.

Como Peter Eisentraut sais, as regras normais de globbing não incluem .. e. (hm, como terminar esta frase?;)

Apenas use -r para torná-lo recursivo e -i para fazer o cp perguntar se você realmente deseja substituir um arquivo.

cp -ri /backup/olduser/* /newuser/
cp -ri /backup/olduser/.* /newuser/
gaqzi
fonte
Geralmente *não corresponde .ou .., mas se você usar .*. Tente echo .*. Você pode excluir .e ..com o seguinte padrão: .[^.]*.
MCH
@ mch: Mas .[^.]*ainda exclui nomes que começam com .. (por exemplo, ...ou ..super-hidden).
Scott
0

Isso funciona para copiar todos os arquivos e diretórios, exceto os diretórios ocultos recursivamente do diretório atual para qualquer lugar:

cp -rf * ^.* 
Seeeve
fonte