Bash copia arquivos de vários diretórios para vários diretórios de backup correspondentes

Bash copia arquivos de vários diretórios para vários diretórios de backup correspondentes

Tenho vários diretórios { dir1,dir2,dir3,dir4} em uma caixa Linux.

Existem vários arquivos em cada diretório (com a mesma extensão, digamos .zip) dos quais desejo fazer backup nos diretórios correspondentes { dir1-bck,dir2-bck,dir3-bck,dir4-bck}. Não preciso fazer backup de toda a pasta, apenas alguns arquivos em cada uma.

Como eu faria para copiar os arquivos do dir1/*.ziparquivo dir1-bck. . . para obter uma lista de diretórios fornecidos. Atualmente estou usando:

cp -r src/dir1/*.zip dest/dir1-bck/
cp -r src/dir2/*.zip dest/dir2-bck/
cp -r src/dir3/*.zip dest/dir3-bck/
cp -r src/dir4/*.zip dest/dir4-bck/

O que funciona, mas tem muito espaço para melhorias.

Examinando a xargspágina de manual e postagens semelhantes no fórum, sinto que é a ferramenta para esse trabalho, mas não consigo acertar.

Responder1

Provavelmente um forloop será o ideal. A forma exata depende de como esses diretórios são nomeados. Pode ser:

cd src || exit 1
for d in "dir"{1..4}; do
   cp -r "$d"/*.zip "../dest/$d-bck/"
done

Notas:

  • É bom trabalhar de dentro de src( cd src), então a variável contém uma string que pode ser usada no caminho de destino sem processamento extra. O caminho de destino foi ajustado acrescentando ../neste caso, mas em geral pode ser como "/full/path/to/dest/$d-bck/".
  • Citei dircaso você substitua um nome por espaços ou algo assim. Eu citei duas vezes $dpelo mesmo motivo emais.
  • Se *.zipforem arquivos, você não precisa do -r.

Alternativamente, a forlinha pode ser:

for d in dir1 dir2 dir3 dir4; do

o que seria útil se você precisasse especificar alguns diretórios nomeados arbitrariamente. Ou ainda:

for d in *; do

Poucas melhorias podem ser feitas, como esta:

( cd src || exit 1
for d in *; do
   dst="../dest/$d-bck/"
   [ -d "$d" ] && mkdir -p "$dst" && cp -- "$d"/*.zip "$dst"
done )

As melhorias:

  • Todo o código é executado em um subshell ( (…)), portanto cdnão afetará o shell atual, mesmo se você colar o código em um terminal. Se tivesse que ser um script independente (executado, não originado), o subshell seria irrelevante.
  • Verificamos se $dé um diretório.
  • Tentamos criar o diretório de destino (caso ele não exista).
  • Continuaremos cpapenas se o diretório de destino existir.
  • Nós usamostraço duplocaso $dcomece com um travessão.

Possíveis problemas:

  • "$d"/*.zippode expandir para muitos itens ( Argument list too long). Seus comandos originais são "falhos" da mesma maneira. Se houver "apenas alguns arquivos em cada" diretório, isso não deverá ser um problema.
  • "$d"/*.zipnão pode expandir ( *permanecerá literal). Não deve causar nenhum dano, mas o diretório de destino será criado antecipadamente. Lógica adicional pode ser desejada para suprimir a criação de diretório nesse caso.
  • O status de saída de todo o snippet depende apenas do último arquivo [ … && mkdir … && cp …. Você precisa de lógica adicional para fazer com que problemas anteriores afetem o status de saída.

informação relacionada