copiar varios archivos a varios directorios

copiar varios archivos a varios directorios

Tengo problemas para copiar muchos archivos en diferentes directorios. Déjame explicarte mejor:

Digamos que tengo lo siguiente en un directorio:

$ ls
file1 file2 file3 file4 file5 dir1 dir2 dir3

y quiero copiar cada archivo* en cada directorio* con un solo comando. Lo he probado con:

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

Mi intención era decirle a xargs que procesara cada directorio* de echo y copiara todos los archivos en la entrada procesada, pero esto y similares no funcionaron. Me gustaría evitar el uso de un script porque es una tarea que tengo que repetir en unos 20 directorios y los nombres de los archivos son ligeramente diferentes, por lo que prefiero modificar un comando en lugar de un script.

Respuesta1

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

Respuesta2

Está cometiendo un pequeño error al utilizar xargs. Sin el parámetro -n, xargs agrega todos los parámetros de entrada al comando y echo dir{1..3}no agregará el retorno de carro necesario entre cada entrada, por lo que xargs considerará el resultado como un parámetro.

xargs tiene una opción -n que puede limitar el número de entradas, y necesita enumerar los directorios con \n o \0 como separador:

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

El comando de búsqueda buscará todos los directorios en el actual y usará \0 como separador (que funciona mejor si tiene directorios con espacios) y xargs usa \0 como separador y ejecutará el comando cada vez con solo 1 parámetro.

Respuesta3

Algo como lo siguiente debería funcionar si realmente tienen esos nombres:

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

Si desea copiar todos los archivos a todos los directorios independientemente del nombre:

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

Respuesta4

Ya casi estás ahí. Debe ejecutar un cpcomando separado para cada directorio de destino, porque cpsolo realiza una copia de cada archivo fuente. El propósito principal de xargses ejecutar un comando sobre múltiples argumentos, pero puede indicarle que pase un solo elemento a la vez con la -nopción. También {} ;es la sintaxis de find … -exec; no lo necesitas (y no puedes usarlo) con xargs.

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

Tenga en cuenta que esto solo funciona si los nombres de sus directorios no contienen ningún espacio en blanco ni ninguno de los caracteres \'", porque xargsno hay forma de saber que esos caracteres son parte de los nombres de los archivos y no citan ni separan los archivos de entrada. Un método alternativo que no presenta ningún problema de este tipo es utilizar un bucle de shell:

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

Todo esto supone que puedes distinguir fácilmente entre archivos y directorios por sus nombres. Si no puede, puede hacer coincidir directorios agregando /al final; por ejemplo, */coincide con todos los directorios en los directorios actuales, foo[0-9]*/coincide con todos los directorios cuyo nombre comienza con fooy un dígito, etc. No existe una forma similar de hacer coincidir solo los directorios que no son directorios en la mayoría de los shells, pero si pasa directorios cpsin ningún argumento para indicarlo Para realizar una copia recursiva, los directorios se ignoran y aparece un mensaje de error.

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

En zsh, puedes usarclasificatorios globalespara que coincida sólo con ciertos tipos de archivos.

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

información relacionada