copiando vários arquivos para vários diretórios

copiando vários arquivos para vários diretórios

Tenho problemas ao copiar muitos arquivos em diretórios diferentes. Deixe-me explicar melhor:

Digamos que eu tenha o seguinte em um diretório:

$ ls
file1 file2 file3 file4 file5 dir1 dir2 dir3

e quero copiar todos os arquivos* em todos os diretórios* com um único comando. Eu tentei com:

 echo dir{1..3} | xargs cp file{1..5} '{}' \;

Minha intenção era dizer ao xargs para processar cada dir* do echo e copiar todos os arquivos na entrada processada, mas isso e similares não funcionaram. Gostaria de evitar o uso de um script porque é uma tarefa que devo repetir em cerca de 20 diretórios e os nomes dos arquivos são um pouco diferentes, então prefiro modificar um comando em vez de um script.

Responder1

echo dir[1-3] | xargs -r -n1 cp file[1-5]

Responder2

Você está cometendo um pequeno erro ao usar xargs. Sem o parâmetro -n, o xargs anexa todos os parâmetros da entrada ao comando e echo dir{1..3}não adicionará o retorno de carro necessário entre cada entrada, portanto o xargs considerará o resultado como um parâmetro.

xargs tem uma opção -n que pode limitar o número de entradas, e você precisa listar os diretórios com \n ou \0 como separador:

find . -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 -n 1 cp file{1..5}

O comando find irá procurar todos os diretórios do atual e usar o \0 como separador (que funciona melhor se você tiver diretórios com espaços) e xargs usa o \0 como separador e iniciar o comando cada vez com apenas 1 parâmetro.

Responder3

Algo como o seguinte deve funcionar se eles realmente tiverem esses nomes:

#!/bin/bash
shopt -s nullglob
for dir in dir*/; do
    cp file* "$dir"
done

Se você deseja copiar todos os arquivos para todos os diretórios, independentemente do nome:

#!/bin/bash
shopt -s nullglob dotglob
for dir in */; do
    for file in *; do
        [[ -f $file ]] && cp "$file" "$dir"
    done
done

Responder4

Você está quase lá. Você precisa executar um cpcomando separado para cada diretório de destino, pois cpfaz apenas uma cópia de cada arquivo de origem. O objetivo principal xargsé executar um comando sobre vários argumentos, mas você pode instruí-lo a passar um único item por vez com a -nopção. Também {} ;é a sintaxe de find … -exec; você não precisa (e não pode usá-lo) com xargs.

echo dir{1..3} | xargs -n 1 cp file{1..5}

Observe que isso só funciona se os nomes dos seus diretórios não contiverem nenhum espaço em branco ou qualquer um dos caracteres \'", porque xargsnão há como saber se esses caracteres fazem parte dos nomes dos arquivos e não estão entre aspas e separando os arquivos de entrada. Um método alternativo que não apresenta esse problema é usar um shell loop:

for d in dirs{1..3}; do
  cp file{1..5} "$d"
done

Tudo isso pressupõe que você possa distinguir facilmente entre arquivos e diretórios por seus nomes. Se não puder, você pode combinar os diretórios adicionando um /no final; por exemplo, */corresponde a todos os diretórios nos diretórios atuais, foo[0-9]*/corresponde a todos os diretórios cujo nome começa com fooum dígito, etc. Não existe uma maneira semelhante de corresponder apenas não-diretórios na maioria dos shells, mas se você passar diretórios para cpsem nenhum argumento para informá-lo para fazer uma cópia recursiva, os diretórios são ignorados com uma mensagem de erro.

for d in */; do
  cp * "$d"
done

No zsh, você pode usareliminatórias globaispara corresponder apenas a determinados tipos de arquivo.

for d in *(/); do
  cp *(.) $d
done

informação relacionada