Linux: copie todos los archivos que coincidan con el patrón del directorio y subdirectorios en un único directorio


30

Si quisiera copiar todos los *.soarchivos de srca dst, lo haría:

cp src/*.so dst

Sin embargo, quiero copiar todos los *.soarchivos de src y se subdivide en dst. ¿Alguna pista?

Respuestas:


34

Tratar:

find src/ -type f | grep -i so$ | xargs -i cp {} dst

17
findpuede hacer coincidir patrones y ejecutar comandos. No es necesario canalizar su salida:find src/ -type f -name '*.so' -exec cp '{}' dst/ ';'
jáquer

1
Sí, puede, sin embargo, a menudo es más fácil leer una tubería, también las capacidades de coincidencia de patrones grepsuperan con creces los patrones de shell simples utilizados en el -nameparámetro find. xargsTambién es mucho más poderoso que el -execparámetro find.
Mike Insch

2
La solución de @jaquer es mucho mejor porque en MacOSX la utilidad xargs no tiene la opción -i. Pero su solución funciona a las mil maravillas.
bialix

Estaba luchando con un mensaje de error en el argumento -i de xargs hasta que leí el comentario de @bialix sobre la solución de jaquer, que funcionó perfectamente en mi Mac. Gracias
svannoy

14

Si está utilizando Bash, puede activar la globstar opción de shell para que coincida con archivos y directorios de forma recursiva:

shopt -s globstar
cp src/**/*.so dst

Si necesita buscar archivos cuyos nombres comiencen con ., y / o archivos en y bajo directorios cuyos nombres comiencen con ., configure la dotglobopción también (por ejemplo, con shopt -s dotglob). Puede configurarlos en un solo comando:

shopt -s globstar dotglob

No copia archivos en subdirectorios que comienzan con a. en su nombre
rboy

7

Probé el comando sugerido por Mike:

find src/ -type f | grep -i so$ | xargs -i cp {} dst

pero terminó volcando todos los archivos en el directorio dstcon sus rutas relativas perdidas.

Para mantener las rutas relativas, el comando debe modificarse para esto:

find src/ -type f | grep -i so$ | xargs -i cp {} dst/{}

55
+1. Sin embargo, esto supone que existen los directorios correspondientes a las rutas de origen relativas dst. En caso de que no sea así, úselo cp --parents. Además, asegúrese de citar los nombres de archivo. Por lo tanto: ... | xargs -i cp --parents "{}" dst(tenga en cuenta que el último argumento para cpahora es "solo" el directorio de destino). El comando se puede hacer aún más corto (y probablemente más rápido) utilizando la -tbandera: ... | xargs cp --parents -t dst.
Stephan202

1
@ Stephan202 tuve que usar... | xargs cp {} --parents -t dst.
warvariuc

3

Otra forma de hacer esto es así:

find src/ -type f -name "*.so" -exec cp {} dst/ \;

Y esto debería reducir el número de cpprocesos: ... -exec cp -t dst/ {} +.
Kamil Maciorowski

¡Hola Kamil! ¡Gracias por el comentario! ¿Puede explicarme cómo su solución agiliza las cosas! Siempre dispuesto a aprender más :)
Kyriakos

Cuando termina -execcon ;, {}se reemplaza por un camino a la vez. Obtiene un separado cppara cada archivo. Con la +sintaxis findreemplaza {}con múltiples resultados (hasta un límite definido por el sistema de longitud de la línea de comando; restricción: {}debe ser lo último antes +, por lo tanto cp -t). Crear y finalizar un proceso es algo relativamente costoso. Por esta razón, es bueno usarlo +cuando esperes muchos resultados. En este caso, copiar muchos archivos puede tomar mucho tiempo de todos modos, por lo que la diferencia puede pasar desapercibida; Sin embargo, es una buena práctica.
Kamil Maciorowski

1

El grep puede reemplazarse usando find's -name :

find src/ -type f -name "*.so" | xargs -i cp {} dst/{}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.