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.