Backup directories with space in directory name

Colin Watson cjwatson at ubuntu.com
Sat Dec 31 04:46:31 UTC 2016


On Fri, Dec 30, 2016 at 09:47:53PM -0600, Jack McGee wrote:
> I am trying to use this perl script to backup a directory, but it fails with
> this error:
> 
> jmcgee at jmcgee-desktop:~$ perl backupsystemrotate.pl
> Backing up /mnt/ntfs-d/My Documents to
> /mnt/media3/backups/desktop/jmcgee-desktop-Friday.tgz
> Fri Dec 30 21:42:57 CST 2016
> 
> tar: Removing leading `/' from member names
> tar: /mnt/ntfs-d/My: Cannot stat: No such file or directory
> 
> and then it proceeds to backup a directory called Documents.
> 
> Adding single quotes to the line inside the double quotes gives this error:

Don't go down the path of trying to add extra layers of quoting to the
backup_files assignment itself.  That way lies madness.  You should have
exactly one layer of quoting there, to protect the value from word
splitting until it's assigned to the variable.

> jmcgee at jmcgee-desktop:~$ cat backupsystemrotate.pl
> #!/bin/bash

This is a shell script, not a Perl script.  You'll probably be a whole
lot less confused in future if you remove the unnecessary ".pl" suffix
(extensions aren't required, and this is a great example of why
extensions that identify the implementation language of an executable
program are usually a bad idea).

Virtually every shell script should start with "set -e" immediately
after the #! line.  You may have to explicitly handle a few errors, but
that's better than your script blundering on and doing something
unexpected after an error.

> tar czf $dest/$archive_file $backup_files

This goes wrong because word splitting happens *after* parameter
expansion in the shell's admittedly rather arcane rules.

The rule of thumb you should apply to quoting in shell scripts is that,
unless you have a specific reason to know otherwise, every $-expansion
should be surrounded by a layer of "".  So this should be:

  tar czf "$dest/$archive_file" "$backup_files"

(Writing "$dest"/"$archive_file" is also correct, but cumbersome and
noisy.)

This rule applies recursively if you have $ inside something like
$(...), so something like:

  $(expr $foo * 2)

... should be written as:

  "$(expr "$foo" * 2)"

There are a few cases where this rule of thumb isn't appropriate, but
they're comparatively rare.  There are some more cases where it's
unnecessary but harmless.  Still, you'll go wrong a lot less often if
you start from the assumption that all $ characters must be quoted and
avoid quoting only in carefully-selected situations than you will if you
take the opposite approach.

Going back to your attempts to fix this by adding more quoting to
backup_files, one important thing to understand is that you can't fix
quoting problems correctly by adding more quoting to the raw text you're
dealing with.  You always need to ensure appropriate quoting at the
point when things are *expanded*: $variable expansions into the contents
of that variable name, $(...) command substitutions into the output of
that command, and so on.

> ls -lh $dest/

This similarly needs quoting:

  ls -lh "$dest/"

-- 
Colin Watson                                       [cjwatson at ubuntu.com]




More information about the ubuntu-users mailing list