6 votos

BASH - combinación de directorios cuando se utiliza mv

Acabo de empezar a utilizar BASH, así que me puedo mover todo el contenido de un directorio a otro. Pero el problema es que me lo esperaba para combinar los directorios. Estoy usando cron job para ejecutar esta secuencia de comandos.

#!/bin/bash

shopt -s dotglob nullglob
mv mv_schedule/* public_html/

Fuente: /mv_schedule/ (que contiene los archivos/carpetas)

/files/
4.html
5.html
/assets/
sitemap.xml

Destino: /public_html/ (anterior ya existen carpetas)

/files/
1.html
2.html
3.html
/assets/
sitemap.xml

Así que lo que yo quiero, es para todos los nuevos archivos de los directorios dentro de la /mv_schedule/ a combinar con los de /public_html/, y para los archivos que ya existen allí, para ser reemplazados con las que vienen de /mv_schedule/.

Actualmente es devolver a este error a través de correo electrónico cuando yo intente esto con la actual secuencia de comandos:

mv: cannot move `mv_schedule/assets' to `public_html/assets': Directory not empty

¿Cómo puedo solucionar este problema?

7voto

MariusMatutiae Puntos 20077

Qué mensaje de error te está diciendo es que no puede mv el directorio activo porque hay archivos dentro de ella. mv un directorio significa hacer una copia, borrado, y no se puede borrar porque todavía contiene algunos archivos. Esto significa que usted debe mv los archivos dentro de los activos, e incluso los subdirectorios y archivos en subdirectorios dentro de los activos, si es que existen. Pero el comando mv que emitió sólo puede copiar (y borrar) lo que está presente en el interior de la mv_schedule directorio, no de lo que se presente dentro de los subdirectorios (como activo) dentro de mv_schedule.

Lo que queremos es un comando que desciende por el árbol de directorios hasta la última hoja y la copia, algo así como un -r o -R opción en rm, chmod, chown. Sin embargo, mv no tiene esa opción, así que usted tendrá que usar el comando find, que desciende por el árbol de directorios completo de una root que usted especifique, y luego ejecuta una acción especifica. En su caso, un adecuado comando es:

SOURCE_DIR=$1
TARGET_DIR=$2
find $SOURCE_DIR -name '*' -type f -exec mv -f {} $TARGET_DIR \;

Esto se amontonan todos los archivos en un solo directorio de destino. Se supone que pasa la fuente y el directorio de destino como de entrada parámetros de la línea de un script de bash. La opción-f impide pedir confirmación en caso de que se sobrescriban, puede cambiar que a -n (no sobrescribir) o -i (preguntar antes de sobrescribir).

Si por el contrario desea conservar la estructura de directorios, recuerde que el comando cp tiene la capacidad de descender por el árbol de directorios, de modo que usted puede usar, seguido por una rm, ya que este comando también tiene la capacidad de descender de los árboles. Un posible conjunto de comandos es:

SOURCE_DIR=$1
TARGET_DIR=$2
cp -a $SOURCE_DIR $TARGET_DIR
rm -rf $SOURCE_DIR

Aviso la opción-a en cp: conserva las marcas de tiempo y propiedades. Si usted no se preocupan por estas cosas, usted puede usar-R en su lugar.

4voto

Chris Nava Puntos 4048

Hay un más genérico de la discusión de este problema en el Unix de la sección.

Usted puede utilizar el -l opción de la cp de comandos, lo que crea enlaces duros de archivos en el mismo sistema de ficheros en lugar de copias de datos. El siguiente comando copia la carpeta source/folder a una carpeta principal (destination) que ya contiene un directorio con el nombre folder.

cp -rl source/folder destination
rm -r source/folder

Notas:

  • Puede que también desee utilizar la -P (--no-dereference - no de-referencia de enlaces simbólicos) o -a (--archive - conservar todos los metadatos, también incluye -P opción), dependiendo de sus necesidades.
  • A pesar de que hay dos "I/O" pasos a seguir, los pasos son relativamente simples, metadatos de las operaciones que involucran a cero "datos" de las transferencias. Por lo tanto este método es de magnitud más rápido que un cp (sans -l) o rsync basado en la solución.
  • Esto no funciona si las carpetas de origen y destino se encuentran en diferentes sistemas de ficheros

2voto

zaTricky Puntos 137

Excelente respuesta de palswim. (También, gracias por la upvote para los dos últimos puntos necesarios para ser capaz de upvote yo!)

El cp-rl ; rm arregla el problema y con un mínimo de e/S (cp y rsync son estúpidamente caro en ese sentido).

Hay dos pequeños problemas:

  • no es 100% atómico - lleva dos operaciones de e/S (esto se aplica el método de rsync así, como-quitar-la-fuente-de los archivos que en realidad todavía requiere una operación de e/S).
  • no funciona si el origen y el destino están en diferentes sistemas de ficheros

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: