Alex
Alex

Reputation: 44275

How to handle space in filename in bash script?

I want to automate rsyncing, and tried the following code:

TARGET="/media/USB\ DISK/Backup/"
rsync -av --delete ~/Data ${TARGET}

but the execution results in the following error:

rsync: link_stat "/media/USB\" failed: No such file or directory (2)
rsync: mkdir "/home/DISK/BACKUP" failed: No such file or directory (2)

because of the 'space' in the target filename. However, when I echo the command I can use that to run on the shell directly.

How to do it correctly (which brackets, with backslash or without?) and why?

Upvotes: 5

Views: 1917

Answers (3)

lufayang
lufayang

Reputation: 1

Try this. I think the curly braces (parameter expansion) messed it up.

TARGET="/media/USB DISK/Backup/"
rsync -av --delete ~/Data "$TARGET"

Upvotes: 0

Édouard Lopez
Édouard Lopez

Reputation: 43391

You should use quotes around your string. String should be quoted both at declaration and when used/called.

Why use quotes ?

Metacharacters [1]

The first function of quoting is to permit words to contain these metacharacters.

Word splitting and globbing [2]

The second purpose of quoting is to prevent word splitting and globbing.

Type of quotes

For details read the Types of quoting section.

Simple quotes (POSIX)

Everything between single quotes is literal and expands to a single word

Double quotes (POSIX)

permit the shell to parse their contents for those types of expansions that are prefixed with a $ sign - parameter expansions, arithmetic expansions and command substitutions, while treating all other content as literal […]

Bash quoting $'…' and $"…"

Those are non-POSIX (supported by Bash, Ksh93, etc.):

  • $'…' : allow backslash-escaped sequence to be used/expanded (\n, \t, etc.) ;
  • $"…" : for translation

References

Upvotes: 0

John1024
John1024

Reputation: 113814

There are two possibilities:

TARGET="/media/USB DISK/Backup/"
rsync -av --delete ~/Data "${TARGET}"

or

TARGET=/media/USB\ DISK/Backup/
rsync -av --delete ~/Data "${TARGET}"

The first one preserves the space by quoting the whole string. The second one preserves the space by escaping it with a backslash. Also, the argument to the rsync command needs to be quoted.

When the string is both double-quoted and the space is preceded by a backslash, as in TARGET="a\ b", the result is that TARGET contains a literal backslash which is probably not what you wanted. For more details, see the section entitled "Quoting" in man bash.

Upvotes: 12

Related Questions