Copiando um único arquivo para vários diretórios usando cp

12

Esta pergunta é uma sequela das minhas perguntas anteriores, Criando vários diretórios usando mkdir .

Estou usando o shell bash . Eu criei cinquenta diretórios, cada um começando com o prefixo "s", usando o comando:

mkdir $(printf "s%02i " $(seq 1 50))

que é preenchido com o segundo dígito com zeros. Ou seja, os diretórios que obtemos estão no formato s01 , s02 , ..., s49 , s50 .

Agora, gostaria de usar cp para copiar um único arquivo (por exemplo, test.txt ) para cada um dos cinquenta diretórios. É possível fazer isso de uma maneira análoga à acima? Por exemplo, o seguinte trabalho? Eu sou relativamente novo no Unix / Linux, então eu realmente não quero tentar isso até que alguém, por favor, me dê uma indicação de que é seguro.

cp test.txt $ (printf "s% 02i.txt" $ (seq 1 50))

Olhando para a página man para cp , não parece que cp suporte vários destinos como este, no entanto:

NAME
       cp - copy files and directories

SYNOPSIS
       cp [OPTION]... [-T] SOURCE DEST
       cp [OPTION]... SOURCE... DIRECTORY
       cp [OPTION]... -t DIRECTORY SOURCE...

DESCRIPTION
       Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.

       Mandatory  arguments  to  long  options are mandatory for short options
       too.
    
por Andrew 24.09.2012 / 18:02

4 respostas

7

Se você quisesse usar a saída do seu comando para copiar o arquivo para cada diretório usando cp , você sempre poderia canalizá-lo para xargs :

printf "s%02i " $(seq 1 50) | xargs -n 1 cp test.txt

Não deve haver qualquer preocupação sobre a segurança da análise da saída, já que você conhece seu formato e conteúdo antes da mão - o risco de encontrar meta-caracteres e espaço nos nomes dos arquivos não é realmente um problema aqui.

Como alternativa, supondo que os diretórios já existam, você poderia tentar algo como:

find . -maxdepth 1 -type d -name 's[0-9][0-9]' -print0 | xargs -0 -I {} cp test.txt {}

ou sem pipe:

find . -maxdepth 1 -type d -name 's[0-9][0-9]' -exec cp test.txt {} \;

Os dois últimos comandos encontrarão quaisquer arquivos no diretório atual e cp test.txt para eles. A opção -maxdepth 1 evitará qualquer subdiretório que receber o arquivo também. Esteja avisado que 's[0-9][0-9]' está correspondendo a s seguido por quaisquer dois dígitos, o que significa que, se por algum motivo você tiver s99 no cwd , ele também receberá uma cópia de test.txt .

    
por 24.09.2012 / 18:31
8

Você também pode deixar o shell fazer as iterações com um loop for . Essa é a maneira mais básica que não depende de ferramentas externas como parallel ou xargs , e acho mais fácil de entender:

for name in $(printf "s%02i " $(seq 1 50)); do
    mkdir $name
    cp test.txt $name
done

Existem milhões de outras formas de escrever isto, por exemplo:

for name in $(seq -w 1 50); do
    mkdir s$name
    cp test.txt s$name
done

Se você quiser verificar o que seria executado antes de fazer isso, você pode fazer algo como prefixar os comandos com echo , que imprimirá a linha em vez de executá-la:

for name in $(seq -w 1 50); do
    echo mkdir s$name
    echo cp test.txt s$name
done

saídas:

mkdir s01
cp test.txt s01
mkdir s02
cp test.txt s02
mkdir s03
cp test.txt s03
# etc.
    
por 24.09.2012 / 19:04
4

De acordo com isso: link não é possível copiar um arquivo para vários destinos. Verifique o link, pois ele mostra outra maneira de fazer isso.

    
por 24.09.2012 / 18:31
2

Você também pode usar o paralelo do GNU. Supondo que você esteja no diretório contendo text.txt e seus 50 dirs estão localizados em /my/50dirs/path (como /my/50dirs/path/s01 , /my/50dirs/path/s02 etc) você executaria:

seq -w 01 50 | parallel -j1 cp text.txt /my/50dirs/path/s{}
    
por 25.09.2012 / 01:49

Tags