简体   繁体   English

用空格存储目录名的bash变量

[英]bash variable to store directory names with spaces

I'm writing a bash script to collect some directories (where conditions are met) and rsync those to a remote location.我正在编写一个 bash 脚本来收集一些目录(满足条件的地方)并将它们rsync到远程位置。 Overall the script looks like this;总的来说,脚本看起来是这样的;

sources=""
for d in /somewhere/* ; do 
  if $d meets condition; then
    sources="$sources $(printf %q "$d")"
  fi
done
if [ ! -z $sources ] ; then 
  rsync -vrz $sources /remote/target/
fi

Note that I'm using printf %q to escape spaces in directory names.请注意,我使用printf %q来转义目录名称中的空格。 However when there are spaces in directory names, for example when "/somewhere/dir name" met the condition, the rsync thinks that as two directories and fails to run;但是当目录名中有空格时,例如"/somewhere/dir name"满足条件时,rsync认为是两个目录而无法运行;

(at /home/u/) $ bash script.sh

sending incremental file list
rsync: link_stat "/somewhere/dir\" failed: No such file or directory (2)
rsync: link_stat "/home/u/name" failed: No such file or directory (2)

rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1196) [sender=3.1.2]

If I just print the rsync command by changing the last line to如果我只是通过将最后一行更改为来打印 rsync 命令

echo rsync -vrz $sources /remote/target/

it looks just fine.它看起来很好。

(at /home/u/) $ bash script.sh
rsync -vrz /somewhere/dirname /somewhere/dir\ name /remote/target

But using set -x shows something wacky going on.但是使用set -x显示了一些古怪的事情。

(at /home/u/) $ bash script.sh
+ rsync -vrz /somewhere/dirname '/somewhere/dir\' name /remote/target
sending incremental file list
rsync: link_stat "/somewhere/dir\" failed: No such file or directory (2)
rsync: link_stat "/home/u/name" failed: No such file or directory (2)

rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1196) [sender=3.1.2]

I also tried to use double quoted directory names instead of printf %q but it didn't work either, with a slightly different reason.我也尝试使用双引号目录名而不是printf %q但它也不起作用,原因略有不同。

(at /home/u/) $ bash script.sh
+ rsync -vrz '"/somewhere/dirname"' '"/somewhere/dir' 'name"' /remote/target
sending incremental file list
rsync: change_dir "/home/u//"/somewhere" failed: No such file or directory (2)
rsync: change_dir "/home/u//"/somewhere" failed: No such file or directory (2)
rsync: link_stat "/home/u/name"" failed: No such file or directory (2)

sent 20 bytes  received 12 bytes  64.00 bytes/sec
total size is 0  speedup is 0.00
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1196) [sender=3.1.2]

Where are those single quotes around some arguments coming from and what is the best way to collect directories with spaces in a single-lined variable for using as sources in cp , mv , or rsync ?那些围绕某些参数的单引号来自哪里,在单行变量中收集带有空格的目录以用作cpmvrsync源的最佳方法是什么?

Use an array instead.改用数组。

sources=()
for d in /somewhere/* ; do 
  if $d meets condition; then
    sources+=("$d")
  fi
done
if [ "${sources[*]}" ]; then 
  rsync -vrz "${sources[@]}" /remote/target/
fi

The single quotes output with set -x are just for disambiguation, so you can see exactly where actual literal spaces go (as opposed to syntactic spaces which are argument separators).使用set -x输出的单引号只是为了消除歧义,因此您可以准确地看到实际文字空间的位置(与作为参数分隔符的语法空间相反)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM