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 cp
comando separado para cada directorio de destino, porque cp
solo realiza una copia de cada archivo fuente. El propósito principal de xargs
es ejecutar un comando sobre múltiples argumentos, pero puede indicarle que pase un solo elemento a la vez con la -n
opció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 xargs
no 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 foo
y 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 cp
sin 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