bash - 如何在 bash 的源函数中的 scp 命令中正确转义空格形成多个文件
问题描述
我在我的 .bashrc 中构建了一个函数,当它尝试 scp 名称中带有空格的文件时会中断,但是如果我直接在 shell 中运行该函数生成的命令输出,它似乎工作正常。
我试过转义空格,以及单引号和双引号的几种变体,下面的版本是我最接近工作的版本,我不明白为什么它会失败。
来自 .bashrc
push2() {
# parse args, build file list, get suffix from final arg
files=""
i=1
orig_IFS=$IFS; IFS=":"
for arg in $*; do
if [ "$i" = "$#" ]; then
suffix=$arg
else
files="$files $(echo $arg | sed -r 's/ /\\ /')" #escape spaces
fi
i=$(($i+1))
done
IFS=$orig_IFS
# determine prefix and proxy
gen_prefix $suffix
# output generated command for debugging
echo "scp $scp_proxy$files testuser@$prefix$suffix:"
# run command
scp $scp_proxy$files testuser@$prefix$suffix:
}
即使输出命令字符串正确转义,运行该函数似乎仍然失败
root@DHCP-137:~$ push2 temp* 42
scp temp temp\ file testuser@10.3.3.42:
temp 100% 6008 1.1MB/s 00:00
temp\: No such file or directory
file: No such file or directory
运行它生成的命令按预期工作
root@DHCP-137:~$ scp temp temp\ file testuser@10.3.3.42:
temp 100% 6008 896.4KB/s 00:00
temp file 100% 0 0.0KB/s 00:00
root@DHCP-137:~$
附加信息:GNU bash,版本 4.4.12(1)-release (x86_64-pc-linux-gnu) - 在 Debian 9 上运行
解决方案
首先,更改您的调用签名,以便后缀在前:
push2 42 ./temp*
那么函数应该简单地定义为
push2 () {
local -a scpProxy
local prefix suffix
suffix=$1
shift
gen_prefix "$suffix"
scp "${scpProxy[@]}" "$@" "testuser@$prefix.$suffix:"
}
看起来gen_prefix
像
gen_prefix () {
case $1 in
42) scpProxy=()
prefix=10.3.3
;;
89) scpProxy=(-o ProxyJump=user@server)
prefix=123.456.789
;;
esac
}
调用后shift
,$@
仅包含您要传输的文件。scpProxy
是一个数组,包含多个要传递给的单独参数scp
;如果它为空,"${scpProxy[@]}"
则将扩展为 0 个参数,而不是空字符串。
(使用./temp*
而不是temp*
防范包含:
并因此可能被误认为远程文件名的匹配项。)
尽管gen_prefix
似乎“全局”定义了它的变量,但实际上只是在调用gen_prefix
的任何范围内定义它们(使用动态范围,而不是词法范围,就像大多数其他常见语言一样)。这两个调用以确保任何分配都留在内部,并且在退出后不可见。bash
local
gen_prefix
push2
push2
作为附加说明,此功能的大部分可以通过合适的ssh
配置消失。.ssh/config
在您的文件中考虑这一点:
Host somehost
User testuser
Hostname 10.3.3.42
Host someotherhost
User testuser
Hostname 123.456.789.89
ProxyJump user@server
现在你根本不需要push2
;赶紧跑
scp temp* somehost:
或者
scp temp* someotherhost:
并且将自动使用正确的地址和选项。ssh
配置替换了所做的一切gen_prefix
,无需调用gen_prefix
,不再需要 wrap scp
。
推荐阅读
- c - 如何返回类型为结构的函数的返回值?
- couchbase - 如何找出所有连接并使用 couchbase 的客户端 IP 并将其发送到日志文件
- javascript - 如何在 Reactive Forms 中重置一组 formControls?
- c++ - 原子compare_exchange,但基于设置的标志,而不是平等?
- php - 从带有连接表的 POST 数组创建 MySQL 搜索查询
- c# - 无法设置边框类的权重属性,无法在 c# Excel 互操作中格式化边框
- laravel - Laravel - 雄辩的关系和变量
- vb.net - 生成带前缀的自动 ID
- linux - 在 Windows 上托管 docker 虚拟机时,是否可以将 docker-nvidia 配置为与 tensorflow-serving 一起使用?
- amazon-web-services - 无服务器框架的 aws iam 策略,仅允许删除部署存储桶