
Neste artigo, serão reveladas algumas coisas não óbvias relacionadas ao uso de
curingas ao copiar, o comportamento ambíguo do comando
cp
ao copiar, bem como maneiras de copiar corretamente um grande número de arquivos sem omissões e falhas.
Suponha que precisamos copiar tudo da pasta / source para a pasta / target.
A primeira coisa que vem à mente é:
cp /source/* /target
Corrija imediatamente este comando para:
cp -a /source/* /target
A opção
-a
adiciona uma cópia de todos os atributos, direitos e adiciona recursão. Quando a reprodução exata dos direitos não é necessária, a opção
-r
é suficiente.
Após a cópia, descobrimos que nem todos os arquivos foram copiados - os arquivos iniciados a partir de um ponto como foram ignorados:
.profile
.local
.mc
e coisas assim.
Por que isso aconteceu?
Como os curingas processam o shell (
bash
em um caso típico). Por padrão, o bash ignora todos os arquivos que começam com pontos, pois os trata como ocultos. Para evitar esse comportamento, precisamos alterar o comportamento do
bash
usando o comando:
shopt -s dotglob
Para salvar essa alteração no comportamento após uma reinicialização, você pode criar o arquivo wildcard.sh com este comando na pasta
/etc/profile.d
(sua distribuição pode ter uma pasta diferente).
E se não houver arquivos no diretório de origem, o shell não poderá substituir nada pelo asterisco, e a cópia também falhará. Contra essa situação, existem
nullglob
e
nullglob
. Precisamos definir
failglob
, o que impedirá a execução do comando.
nullglob
não funcionará, porque converte uma sequência com caracteres curinga que não encontraram correspondências em uma sequência vazia (de comprimento zero), o que causará um erro no
cp
.
No entanto, se houver milhares de arquivos e mais na pasta, a abordagem usando curingas deve ser abandonada por completo. O fato é que o
bash
expande curingas em uma linha de comando muito longa, como:
cp -a /souce/a /source/b /source/c …… /target
Há uma limitação no comprimento da linha de comando que podemos descobrir usando o comando:
getconf ARG_MAX
Obtenha o comprimento máximo da linha de comando em bytes:
2097152
Ou:
xargs --show-limits
Temos algo como:
…. Maximum length of command we could actually use: 2089314 ….
Então, vamos fazer sem curingas.
Vamos escrever
cp -a /source /target
E aqui encontraremos a ambiguidade do comportamento da
cp
. Se a pasta / target não existir, obteremos o que precisamos.
No entanto, se a pasta de destino existir, os arquivos serão copiados para a pasta / target / source.
Nem sempre podemos excluir a pasta / target antecipadamente, pois ela pode conter os arquivos que precisamos e nosso objetivo, por exemplo, é adicionar arquivos ao / target com arquivos de / source.
Se as pastas de origem e destino fossem nomeadas da mesma maneira, por exemplo, copiaríamos de / source para / home / source, então poderíamos usar o comando:
cp -a /source /home
E depois de copiar os arquivos em / home / source, seriam os arquivos complementados de / source.
Essa é a tarefa lógica: podemos adicionar arquivos ao diretório de destino, se as pastas tiverem o mesmo nome, mas se diferirem, a pasta de origem será colocada dentro do receptor. Como copiar arquivos de / source para / target usando cp sem curingas?
Para contornar essa limitação prejudicial, usamos uma solução não óbvia:
cp -a /source/. /target
Quem conhece bem o DOS e o Linux já entendeu tudo: dentro de cada pasta existem 2 pastas invisíveis "." e "..", que são links de pseudo-pastas para os diretórios atuais e superiores.
- Ao copiar, o
cp
verifica a existência e tenta criar / target /. - Esse diretório existe e é / target
- Arquivos de / source copiados para / target corretamente.
Então, penduramos em uma moldura arrojada em nossa memória ou na parede:
cp -a /source/. /target
O comportamento deste comando é inequívoco. Tudo funcionará sem erros, independentemente de você ter um milhão de arquivos ou nenhum.
Conclusões
Se você deseja copiar
todos os arquivos de uma pasta para outra, não usamos curingas; em vez deles, é melhor usar o
cp
em combinação com um ponto no final da pasta de origem. Isso copiará todos os arquivos, incluindo os ocultos, e não falhará com milhões de arquivos ou a ausência completa de arquivos.
Posfácio
O vmspike sugeriu uma variante semelhante do comando:
cp -a -T /source /target
Oz_Alex cp -aT /source /target
ATENÇÃO: o caso da letra
T
importante. Se você confundir, recebe o lixo completo: a direção da cópia muda.
Agradecimentos:
- Empresa RUVDS.COM por seu apoio e pela oportunidade de publicar em seu blog no Habr.
- Por imagem TripletConcept . A imagem é muito grande e detalhada. Você pode abri-la em uma janela separada.
PS Direct erros que você percebe no PM. Eu aumento o carma por isso.
