Equipo cp: copia correcta de carpetas con archivos en *nix

Equipo cp: copia correcta de carpetas con archivos en *nix

En este artículo se revelarán algunas cosas no tan evidentes relacionadas con el uso de comodines al copiar, el comportamiento ambiguo del comando cp al copiar, así como formas que permiten copiar correctamente una gran cantidad de archivos sin omisiones ni errores.

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

Lo primero que se nos ocurre es:

cp /source/* /target

Inmediatamente corregimos este comando a:

cp -a /source/* /target

Clave -a agregará la copia de todos los atributos, permisos y añadirá recursión. Cuando no se requiere una reproducción exacta de los permisos, basta con la opción -r.

Después de la copia, descubrimos que no se copiaron todos los archivos; se ignoraron archivos que comienzan con un punto, como:

.perfil
.local
.mc

y cosas similares.

¿Por qué ocurrió esto?

Porque los comodines son procesados por el shell (bash en un caso típico). Por defecto, bash ignora todos los archivos que comienzan con un punto, ya que los considera ocultos. Para evitar este comportamiento, debemos cambiarlo bash usando el comando:

shopt -s dotglob

Para que este cambio de comportamiento se mantenga después de reiniciar, se puede crear un archivo wildcard.sh con este comando en la carpeta /etc/profile.d (quizás en su distribución la carpeta sea diferente).

Y si en el directorio fuente no hay archivos, el shell no podrá sustituir nada por el asterisco, y la copia también terminará con un error. Para prevenir esta situación, hay opciones failglob y nullglob. Necesitaremos configurar failglob, que no permitirá que el comando se ejecute. nullglob no servirá, ya que convierte una cadena con comodines sin coincidencias en una cadena vacía (de longitud cero), lo que causará un error para cp .

Sin embargo, si en la carpeta hay miles de archivos o más, vale la pena abandonar por completo el enfoque de usar comodines. La razó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 un límite en la longitud de la línea de comando, que podemos conocer usando el comando:

getconf ARG_MAX

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

2097152

O:

xargs --show-limits

Obtendremos algo como:

….
Longitud máxima del comando que podríamos usar: 2089314
….

Así que, evitemos completamente el uso de comodines.

Simplemente escribamos

cp -a /source /target

Y aquí nos encontramos con ambigüedades en el comportamiento cp. Si la carpeta /target no existe, obtendremos lo que necesitamos.

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

No siempre podemos eliminar la carpeta /target de antemano, ya que puede contener archivos que necesitamos y nuestro objetivo, supongamos, es complementar los archivos en /target con archivos de /source.

Si las carpetas de origen y destino tuviesen el mismo nombre, por ejemplo, si estuviéramos copiando de /source a /home/source, podríamos usar el comando:

cp -a /source /home

Y después de la copia, los archivos en /home/source estarían complementados con los archivos de /source.

Aquí hay un acertijo lógico: podemos complementar los archivos en el directorio de destino, si las carpetas tienen el mismo nombre, pero si son diferentes, la carpeta de origen será colocada dentro del destino. ¿Cómo copiar archivos de /source a /target usando cp sin comodines?

Para sortear esta limitación perjudicial, utilizamos una solución no evidente:

cp -a /source/. /target

Aquellos que están familiarizados con DOS y Linux ya lo han entendido todo: dentro de cada carpeta hay 2 carpetas invisibles «.» y «..», que son pseudo carpetas que linkean al directorio actual y al directorio superior.

  • Al copiar cp verifica la existencia y trata de crear /target.
  • Tal directorio existe y es /target
  • Los archivos de /source se han copiado a /target correctamente.

Así que vamos a enmarcar con un borde grueso en nuestra mente o en la pared:

cp -a /source/. /target

El comportamiento de este comando es definitivo. Todo funcionará sin errores independientemente de si tienes un millón de archivos o ninguno.

Conclusiones

Si necesitas copiar cargas de trabajo dejarán de funcionar! archivos de una carpeta a otra, no uses comodines, en su lugar 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.

Póscrito

vmspike propuso 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 te confundes, obtendrás un completo desastre: la dirección de copia cambiará.
Agradecimientos:

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

P.D. Envía errores reportados por mensaje privado. Aumentaré tu karma por esto.

Equipo cp: copia correcta de carpetas con archivos en *nix

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster