LogicalException
LogicalException

Reputation: 596

How can I pass a variable onto a command's parameter in a bash script?

Example bash script demonstrating my problem:

#!/bin/bash

function exclude
{
    BACKUP_EXCLUDES="$BACKUP_EXCLUDES --exclude=\"$1\""
}

exclude "/proc"
exclude "/dev"
exclude "/mnt"
exclude "/media"
exclude "/lost+found"

echo $BACKUP_EXCLUDES

Output:

--exclude="/proc" --exclude="/dev" --exclude="/mnt" --exclude="/media" --exclude="/lost+found"

Perfect! But when I try adding:

rsync -ruvz $BACKUP_EXCLUDES / /some/backup/path

$BACKUP_EXCLUDES is completely ignored with no errors or warnings... Why?

Upvotes: 1

Views: 683

Answers (2)

mpapis
mpapis

Reputation: 53158

you need to use array:

#!/usr/bin/env bash

BACKUP_EXCLUDES=()
function exclude
{
  while
    (( $# ))
  do
    BACKUP_EXCLUDES+=(--exclude="$1")
    shift
  done
}
exclude /proc /dev /mnt /media
exclude "/lost+found"

rsync -ruvz "${BACKUP_EXCLUDES[@]}" / /some/backup/path

the bash explanation: please check @janos answer

the zsh explanation (if it was Zsh): when you used a string variable it was like you passed --exclude="\"/proc\" --exclude=\"/media\" ..." - so it was treated as long path with spaces - which never matched.

Upvotes: 3

janos
janos

Reputation: 124646

It doesn't work because the quotes are included in the individual --exclude parameters. That is, rsync will ignore "/proc" instead of /proc. Of course "/proc" (with quotes) doesn't exist.

If you stick an eval in front of the command it will work, like this:

eval rsync -ruvz $BACKUP_EXCLUDES / /some/backup/path

In this case the --exclude="/proc" (and all others) will be evaluated to --exclude=/proc, that's why it will work.

But I think you should use arrays as proposed by @mpapis, or --exclude-from=FILE as proposed by a comment. Both are much better and cleaner solutions.

Upvotes: 3

Related Questions