Rsync ignora las comillas dobles en el script

Rsync ignora las comillas dobles en el script

Cuando "$exclude_list"se llama a la variable como parámetro, rsync ignora las comillas dobles y de alguna manera incluye la carpeta de inicio incluso si no se menciona en el script. Intento resumirlo en "${exclude_list}", pero eso tampoco ayudó.

Mostrar el contenido de la variable antes de usarla en combinación con rsync, muestra que es correcto.

Otra cosa extraña es que cuando lo hago echo rsync ...el resultado es correcto y no hay errores.

Parte del script bash problemático:

    echo "$exclude_list"
    rsync -av --dry-run "$exclude_list" "$src" "$dest" >> /var/log/rsync.log || {
      sendmail "Error: rsync failed for folder $src."; exit 1; }

Producción:

   --exclude=lost+found
   rsync: [sender] link_stat "/home/user/ --exclude=lost+found" failed: No such file or 
   directory (2)
   rsync error: some files/attrs were not transferred (see previous errors) (code 23) at 
   main.c(1333) [sender=3.2.3]

Aquí está el MCVE:

#!/bin/bash

# List of source folders
SRC_FOLDERS=(
  [0]="/mnt/load-1/"
  [1]="/mnt/load-2/"
)

# List of backup folders
DEST_FOLDERS=(
  [0]="/mnt/load-1-b/"
  [1]="/mnt/load-2-b/"
)

# List of folders to exclude during backup
EXCLUDE_FOLDERS=(
  "lost+found"
  "lost-found"
)

  # Form the exclude list for rsync
  for exclude_folder in "${EXCLUDE_FOLDERS[@]}"; do
    exclude_list="$exclude_list --exclude=$exclude_folder"
  done

# Loop through each folder pair
for i in "${!SRC_FOLDERS[@]}"; do
  src=${SRC_FOLDERS[$i]}
  dest=${DEST_FOLDERS[$i]}

    rsync -av --dry-run "$exclude_list" "$src" "$dest"

done

Respuesta1

El problema está en

for exclude_folder in "${EXCLUDE_FOLDERS[@]}"; do
  exclude_list="$exclude_list --exclude=$exclude_folder"
done

Se itera sobre una matriz EXCLUDE_FOLDERSy se crea una variable que no es de matriz exclude_lista partir de ella. Cuando luego se hace referencia a él como "$exclude_list", el shell lo expande a una sola palabra.

Antes de que el forbucle exclude_listesté vacío. La primera asignación dentro del bucle hace que la variable comience con --exclude…. Tenga en cuenta el espacio inicial. Debido a este espacio rsyncno se reconoce esta palabra como una opción; lo reconoce como uncamino relativo. Creo que su directorio de trabajo actual es /home/user/. Por lo tanto, la ruta absoluta es /home/user/ --exclude=…, dicho archivo no existe, esto es lo que indica el error.

Incluso si el espacio principal no estuviera allí y exclude_listse creara de alguna manera como --exclude=… --exclude=…, seguiría siendo incorrecto. "$exclude_list"siempre se expande a una sola palabra. Desea que cada uno --exclude=…sea un argumento independiente rsync.

No citar $exclude_listpuede funcionar, aunque es una mala solución; p.ejfallará (o puede) fallar si los elementos EXCLUDE_FOLDERScontienen espacios, tabulaciones o nuevas líneas (o comodines que activan el globbing).

Por favor lee¿Cómo podemos ejecutar un comando almacenado en una variable?En Bash suele ser mejor utilizar una matriz. Haz exclude_listuna matriz:

for exclude_folder in "${EXCLUDE_FOLDERS[@]}"; do
  exclude_list+=("--exclude=$exclude_folder")
done

Luego en la invocación de rsyncuso "${exclude_list[@]}".

información relacionada