【问题标题】:bash variable to store directory names with spacesbash 变量来存储目录名和空格
【发布时间】:2021-03-07 23:28:51
【问题描述】:

我正在编写一个 bash 脚本来收集一些目录(满足条件)和rsync 那些到远程位置。总体而言,脚本如下所示;

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

请注意,我使用printf %q 来转义目录名称中的空格。 但是当目录名中有空格时,比如"/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]

如果我只是通过将最后一行更改为来打印 rsync 命令

echo rsync -vrz $sources /remote/target/

看起来还不错。

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

但是使用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]

我也尝试使用双引号目录名称而不是 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]

一些参数周围的单引号是从哪里来的?在单行变量中收集带有空格的目录以用作cpmvrsync 中的源的最佳方法是什么?

【问题讨论】:

标签: bash rsync


【解决方案1】:

改为使用数组。

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

带有set -x 的单引号输出只是为了消除歧义,因此您可以准确地看到实际文字空格的位置(与作为参数分隔符的句法空格相反)。

【讨论】:

  • 你忘了双引号$d吗?
  • 我的荣幸 :-)
猜你喜欢
  • 1970-01-01
  • 2022-08-03
  • 2014-05-18
  • 1970-01-01
  • 2011-08-14
  • 2012-08-08
  • 2021-07-17
  • 1970-01-01
  • 2019-06-15
相关资源
最近更新 更多