varios todos significa que para otro mover manipulaciĆ³n los directorios directorio crear copiar comandos comando carpeta archivos unix shell

todos - Estructura de carpeta de aplanamiento de copia de archivo de shell de Unix



mover varios archivos en linux (5)

En el shell bash de UNIX (específicamente Mac OS X Leopard), ¿cuál sería la forma más sencilla de copiar cada archivo que tenga una extensión específica desde una jerarquía de carpetas (incluidos los subdirectorios) a la misma carpeta de destino (sin subcarpetas)?

Obviamente, existe el problema de tener duplicados en la jerarquía de origen. No me importaría si se sobrescriben.

Ejemplo: necesito copiar cada archivo .txt en la siguiente jerarquía

/foo/a.txt /foo/x.jpg /foo/bar/a.txt /foo/bar/c.jpg /foo/bar/b.txt

A una carpeta llamada ''dest'' y obtener:

/dest/a.txt /dest/b.txt


El único problema con la solución de Magnus es que genera un nuevo proceso de "cp" para cada archivo, que no es muy eficiente, especialmente si hay una gran cantidad de archivos.

En Linux (u otros sistemas con coreutils de GNU) puedes hacer:

find . -name "*.xml" -print0 | xargs -0 echo cp -t a

(El -0 le permite funcionar cuando sus nombres de archivo tienen caracteres extraños, como espacios, en ellos).

Lamentablemente, creo que los Mac vienen con herramientas de estilo BSD. ¿Alguien sabe un equivalente "estándar" al interruptor "-t"?


En bash:

find /foo -iname ''*.txt'' -exec cp /{/} /dest/ /;

find encontrará todos los archivos debajo de la ruta /foo coincidan con el comodín *.txt , sin distinción de mayúsculas y minúsculas (eso es lo que significa -iname ). Para cada archivo, find ejecutará cp {} /dest/ , con el archivo encontrado en lugar de {} .


En cuanto a la página man para cp en una caja de FreeBSD, no hay necesidad de un modificador -t. cp asumirá que el último argumento en la línea de comando será el directorio de destino si se pasan más de dos nombres.


Si realmente desea ejecutar solo un comando, ¿por qué no usar uno y ejecutarlo? Al igual que:

$ find /foo -name ''*.txt'' | xargs echo | sed -e ''s/^/cp /'' -e ''s|$| /dest|'' | bash -sx

Pero eso no importará demasiado en cuanto a rendimiento, a menos que hagas esto mucho o tengas una tonelada de archivos. Sin embargo, ten cuidado con las colusiones de nombres. Noté en las pruebas que GNU cp al menos advierte de colisiones:

cp: will not overwrite just-created `/dest/tubguide.tex'' with `./texmf/tex/plain/tugboat/tubguide.tex''

Creo que el más limpio es:

$ find /foo -name ''*.txt'' | xargs -i cp {} /dest

Menos sintaxis para recordar que la opción -exec.


Las respuestas anteriores no permiten colisiones de nombres, ya que al solicitante no le importó que se sobrescribieran los archivos.

Me importa que los archivos se sobrescriban, por lo que surgió un enfoque diferente. Reemplazando cada / en la ruta con - mantenga la jerarquía en los nombres, y coloca todos los archivos en una carpeta plana.

Usamos find para obtener la lista de todos los archivos, luego awk para crear un comando mv con el nombre de archivo original y el nombre de archivo modificado y luego pasarlos a bash para su ejecución.

find ./from -type f | awk ''{ str=$0; sub(//.///, "", str); gsub(////, "-", str); print "mv " $0 " ./to/" str }'' | bash

donde ./from y ./to son directorios a mv desde y hacia.