Comando cp: copiar carpetas de archivos a * nix correctamente



En este artículo, se revelarán algunas cosas obvias relacionadas con el uso de comodines al copiar, el comportamiento ambiguo del comando cp al copiar, así como las formas de copiar correctamente una gran cantidad de archivos sin omisiones y bloqueos.

Supongamos que necesitamos copiar todo desde la carpeta / source a la carpeta / target.

Lo primero que viene a la mente es:

 cp /source/* /target 

Inmediatamente arregle este comando para:

 cp -a /source/* /target 

El -a agregará una copia de todos los atributos, derechos y agregará recursividad. Cuando no se requiere la reproducción exacta de los derechos, el -r es suficiente.

Después de copiar, encontramos que no todos los archivos fueron copiados, los archivos que comienzan desde un punto como fueron ignorados:

.profile
.local
.mc

y similares

¿Por qué sucedió esto?

Porque los comodines procesan el shell ( bash en un caso típico). Por defecto, bash ignorará todos los archivos que comienzan con puntos, ya que los trata como ocultos. Para evitar este comportamiento, tenemos que cambiar el comportamiento de bash usando el comando:

 shopt -s dotglob 

Para guardar este cambio de comportamiento después de reiniciar, puede crear el archivo wildcard.sh con este comando en la carpeta /etc/profile.d (su distribución puede tener una carpeta diferente).

Y si no hay archivos en el directorio de origen, el shell no puede sustituir nada por el asterisco, y la copia también fallará. Frente a esta situación, hay nullglob failglob y nullglob . Necesitamos establecer failglob , lo que impedirá que se ejecute el comando. nullglob no funcionará, porque convierte una cadena con comodines que no han encontrado coincidencias en una cadena vacía (de longitud cero), lo que causará un error para cp .

Sin embargo, si hay miles de archivos y más en la carpeta, entonces el enfoque con comodines debería abandonarse por completo. La cuestión es que bash expande los comodines en una línea de comando muy larga como:

 cp -a /souce/a /source/b /source/c …… /target 

Hay una limitación en la longitud de la línea de comando, que podemos encontrar usando el comando:

 getconf ARG_MAX 

Obtenga la longitud máxima de la línea de comando en bytes:

 2097152 

O:

 xargs --show-limits 

Tenemos algo como:

 …. Maximum length of command we could actually use: 2089314 …. 

Entonces, vamos a hacerlo sin comodines en absoluto.

Solo escribamos

 cp -a /source /target 

Y aquí encontraremos la ambigüedad del comportamiento cp . Si la carpeta / target no existe, obtenemos lo que necesitamos.

Sin embargo, si la carpeta de destino existe, los archivos se copiarán en la carpeta / target / source.

No siempre podemos eliminar la carpeta / target de antemano, ya que puede contener los archivos que necesitamos y nuestro objetivo, por ejemplo, es agregar archivos a / target con archivos de / source.

Si las carpetas de origen y destino se nombraran de la misma manera, por ejemplo, copiaríamos de / source a / home / source, entonces podríamos usar el comando:

 cp -a /source /home 

Y después de copiar los archivos en / home / source serían los archivos complementados de / source.

Tal es la tarea lógica: podemos agregar archivos al directorio de destino, si las carpetas tienen el mismo nombre, pero si difieren, la carpeta de origen se colocará dentro del receptor. ¿Cómo copiar archivos de / source a / target usando cp sin comodines?

Para evitar esta limitación dañina, utilizamos una solución no obvia:

 cp -a /source/. /target 

Aquellos que conocen bien DOS y Linux ya lo entendieron todo: dentro de cada carpeta hay 2 carpetas invisibles "". y "..", que son enlaces de pseudocarpetas a los directorios actuales y superiores.

  • Al copiar, cp comprueba la existencia e intenta crear / target /.
  • Tal directorio existe y es / target
  • Archivos de / fuente copiados a / destino correctamente.

Entonces, colgamos en un marco audaz en nuestra memoria o en la pared:

 cp -a /source/. /target 

El comportamiento de este comando es inequívoco. Todo funcionará sin errores, independientemente de si tiene un millón de archivos o ninguno.

Conclusiones


Si desea copiar todos los archivos de una carpeta a otra, no usamos comodines, en lugar de ellos es mejor usar cp en combinación con un punto al final de la carpeta de origen. Esto copiará todos los archivos, incluidos los ocultos, y no fallará con millones de archivos o la ausencia total de archivos.

Epílogo


vmspike sugirió una variante similar del comando:

 cp -a -T /source /target 

Oz_Alex
 cp -aT /source /target 

ATENCIÓN: el caso de la letra T importa. Si lo mezclas, obtienes la basura completa: la dirección de la copia cambiará.

Agradecimientos

  • Empresa RUVDS.COM por su apoyo y la oportunidad de publicar en su blog en Habré.
  • Por imagen TripletConcept . La imagen es muy grande y detallada, puede abrirla en una ventana separada.

PS Errores directos que notas en PM. Aumento el karma para esto.



Source: https://habr.com/ru/post/471092/


All Articles