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?

Albus Dumbledore
fuente

Respuestas:

34

Tratar:

find src/ -type f | grep -i so$ | xargs -i cp {} dst
Mike Insch
fuente
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
jáquer
fuente
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/{}
Ilya Druker
fuente
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/ \;
Kyriakos
fuente
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/{}
Th. Thielemann
fuente