Copia di un singolo file in più directory usando cp


12

Questa domanda è una sorta di sequel della mia domanda precedente, Creazione di numerose directory usandomkdir .

Sto usando la bashshell. Ho creato cinquanta directory, ognuna che inizia con il prefisso "s", usando il comando:

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

che passa alla seconda cifra con zeri. Cioè, le directory che ottengo sono della forma s01, s02, ..., s49, s50.

Ora vorrei usare cpper copiare un singolo file (ad esempio test.txt) in ciascuna delle cinquanta directory. È possibile farlo in un modo analogo a quello sopra? Ad esempio, funzionerebbe il seguente? Sono relativamente nuovo su Unix / Linux, quindi non voglio davvero provare questo fino a quando qualcuno per favore non mi dà un'indicazione che è sicuro.

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

Guardando la manpagina per cp, non sembra cpsupportare più destinazioni come questa, tuttavia:

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.

Risposte:


7

Se si desidera utilizzare l'output del comando per copiare il file in ciascuna directory utilizzando cp, è sempre possibile reindirizzarlo a xargs:

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

Non ci dovrebbero essere dubbi sulla sicurezza dell'analisi dell'output poiché si conosce prima il suo formato e contenuto - il rischio di incontrare meta caratteri e spazio nei nomi dei file non è davvero un problema qui.

In alternativa, supponendo che le directory esistano già, potresti provare qualcosa del tipo:

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

o senza tubo:

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

Gli ultimi due comandi troveranno tutti i file nella directory corrente e cp test.txtper loro. L' -maxdepth 1opzione eviterà che anche qualsiasi sottodirectory riceva il file. Tieni presente che 's[0-9][0-9]'corrisponde a sseguito da due cifre qualsiasi, il che significa che se per qualche motivo hai s99nel cwd, riceverà anche una copia di test.txt.


8

Puoi anche lasciare che la shell esegua le iterazioni con un forciclo. Questo è il modo più semplice che non si basa su strumenti esterni come parallelo xargse trovo che sia più facile da capire:

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

Ci sono un milione di altri modi per scrivere questo, ad esempio:

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

Se vuoi verificare cosa verrebbe eseguito prima di farlo, puoi fare qualcosa come anteporre i comandi echo, che stamperà la linea anziché eseguirla:

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

uscite:

mkdir s01
cp test.txt s01
mkdir s02
cp test.txt s02
mkdir s03
cp test.txt s03
# etc.


2

Puoi anche usare GNU parallel . Supponendo che tu sia nella directory contenente text.txt e che le tue 50 directory si trovino in /my/50dirs/path(come /my/50dirs/path/s01, /my/50dirs/path/s02ecc.) Dovresti eseguire:

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

2
Meglio farlo parallel -j1, altrimenti ci sarà un lavoro per core, e su una macchina multicore i lavori competeranno per IO.
Gilles 'SO- smetti di essere malvagio' il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.