0

I'm trying to automate a backup script with attic, but I'm stuck on this issue: the actual attic command performs differently when executed from the script and when executed directly in the terminal.

The script builds and executes the command:

/usr/bin/attic create --stats --verbose --exclude '/home/.cache' /media/attic-backup/paolo.attic::2016-08-27 /home

the command outputs the files backuped up from attic:

/home
/home/.attic
/home/.attic/keys
/home/.cache
/home/git
/home/git/.bash_history
etc etc

The /home/.cache directory should have been skipped...

However, if I execute the same command from the terminal I get:

$ /usr/bin/attic create --stats --verbose --exclude '/home/.cache' /media/attic-backup/paolo.attic::2016-08-27 /home
/home
/home/.attic
/home/.attic/keys
/home/git
/home/git/.bash_history
etc etc

Now the /home/.cache directory has been skipped.

It's not a matter of sudo.

Why the command in the script behaves differently?

1 Answer 1

1

When you say the script "builds" the command, do you mean it stores it in a string (variable), and then tries to execute the string as a command? If so, putting quotes inside the string ('/home/.cache') won't do what you expect, because the quotes are treated as data and passed to the command as part of the argument, rather than being parsed and removed before it's passed as an argument. Essentially, this means that rsync was being told to exclude '/home/.cache' rather than just /home/.cache. See BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail! for more info.

If you're trying to build the command piece-by-piece, usually the best way to do it is with an array. Something like this:

atticcmd=(/usr/bin/attic create --stats --verbose --exclude '/home/.cache' /media/attic-backup/paolo.attic::2016-08-27 /home)
"${atticcmd[@]}"

Or you can build only a part of it in an array:

atticopts=(--stats --verbose)
for e in "${excludes[@]}"; do
    atticopts+=(--exclude "$e")
done
/usr/bin/attic create "${atticopts[@]}" /media/attic-backup/paolo.attic::2016-08-27 /home
3
  • I created the array ATTIC_COMMAND_ELEMENTS with elemens of the form --exclude '/home/.cache', but /usr/bin/attic create "${ATTIC_COMMAND_ELEMENTS[@]}" "$REPOSITORY::"`date +%Y-%m-%d--%H.%M` /home doesn't work, I get attic create: error: argument ARCHIVE: "--exclude '/home/.cache'": No archive specified. Why?!? Commented Aug 27, 2016 at 17:48
  • 1
    @PaoloBenvenuto "--exclude" and "/home/.cache" should be two separate elements (since they'll be separate arguments to attic), and the single-quotes should not be included in the value -- quotes go around data, not in data. Note that as shell arguments, '/home/.cache', "/home/.cache", and /home/.cache are all exactly equivalent -- the quotes (if any) influence how the string is parsed (whether various kinds of substitutions and expansions are done, none of which are relevant here), and then removed before the argument is passed to the command. Commented Aug 27, 2016 at 20:40
  • 1
    Also, you can use set -x to make the shell print the command it's about to execute, showing what it thinks is happening. Or rather, it prints an equivalent command line, which can be a bit confusing. I'd try using set -x in an interactive shell, running the command (the one that works) manually, and looking at how the shell interprets it. Then add set -x to the script just before the command that's failing (and `set +x just after it), and compare to see what's different. Commented Aug 27, 2016 at 20:44

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.