我遇到一个奇怪的问题,我认为它与文件/目录通配有关
脚本
echo "tar -zcvf $file $base/$target $exclude_args"
cd $base && tar -zcvf $file $base/$target $exclude_args
输出
tar -zcvf www_2017-04-24.tar.gz /var/www --exclude '/var/www/bak/*/*' --exclude '/var/www/test'
运行脚本时排除路径被省略(每个目录都被 gzip 压缩)
当直接从 putty 运行输出时,/var/www/bak/*/*
下的目录被排除在 gzip 之外
更新
parse_exclude_paths (){
# escape forward slashes to avoid the paths to expand
args=$(echo "$exclude" | sed 's,/,\\\/,g')
args=$(printf " --exclude '%s'" $args)
# strip escapes
echo "$args" | sed 's,\\\/,/,g'
}
exclude="/var/www/bak/*/* /var/www/test"
exclude_args=''
if [ ! -z "$exclude" ]; then
exclude_args="$(parse_exclude_paths "$exclude")"
fi
更新2
如果命令是通过 SSH 发送的,则没有问题,并且排除路径会从 gzip 中排除
ssh root@$host 'cd '"$base"' && tar -zcvf $file '"$base/$target $exclude_args"
最佳答案
我查看了您的问题历史记录,发现您熟悉 PHP。这是 PHP 中的等效问题:
function foo($arg1, $arg2) {
echo "You passed $arg1 and $arg2\n";
}
$var='"one", "two"';
echo "Running: foo($var);\n";
foo($var);
The echo prints
Running: foo("one", "two");
and that command works just fine if you copy-paste it!Why does
foo($var);
instead writePHP Warning: Missing argument 2 for foo()
?
答案当然是变量中的文字引号与函数的调用方式无关。这在 PHP 和 shell 中都是一样的。
PHP 和 Bash 中的解决方案都是使用数组:
#!/bin/bash
file="www_2017-04-24.tar.gz"
base="/var"
target="www"
exclude_args=( --exclude '/var/www/bak/*/*' )
cd "$base" && tar -zcvf "$file" "$base/$target" "${exclude_args[@]}"
sh
更原始,不支持任意数组,但我们可以重用位置参数来达到同样的效果:
#!/bin/sh
file="www_2017-04-24.tar.gz"
base="/var"
target="www"
set -- --exclude '/var/www/bak/*/*' # Now assigned to $1, $2, etc
cd "$base" && tar -zcvf "$file" "$base/$target" "$@"
另一种选择是使用 eval
将字符串重新解释为 shell 命令。这意味着任何可以影响您的变量的人都可以接管您的系统,但如果所有变量都来自具有同等权限的用户,这可能没问题:
eval "tar -zcvf $file $base/$target $exclude_args"
关于linux - 从终端执行命令与从脚本执行命令 - 带通配符的路径 - 防止 glob 扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43593393/