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/*.zip
arquivo 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 xargs
página de manual e postagens semelhantes no fórum, sinto que é a ferramenta para esse trabalho, mas não consigo acertar.
Responder1
Provavelmente um for
loop 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
dir
caso você substitua um nome por espaços ou algo assim. Eu citei duas vezes$d
pelo mesmo motivo emais. - Se
*.zip
forem arquivos, você não precisa do-r
.
Alternativamente, a for
linha 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 (
(…)
), portantocd
nã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
cp
apenas se o diretório de destino existir. - Nós usamostraço duplocaso
$d
comece com um travessão.
Possíveis problemas:
"$d"/*.zip
pode 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"/*.zip
nã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.