我刚刚读了Linux scp 命令问题问题,它提醒我,我经常忘记在 scp 命令的主机部分指定冒号,因此在本地复制文件而不是复制到远程主机,例如我
scp foo host
代替
scp foo host:
但我从未使用 scp 在本地复制文件。因此,我想知道如果两个(源和目标)参数都引用本地文件,是否有办法让 scp 失败。
答案1
您可以在 Bash 中编写一个包装函数并将其命名为scp
,用于getopts
将选项处理为新数组,将源和目标保留在位置参数中,然后检查这些参数是否存在“@”和“:”,如果不存在,则发出错误消息。如果存在,则使用scp
类似 的命令调用实际函数command scp "${args[@]}" "$source" "$dest"
。该command
命令使 Bash 调用在 中找到的程序,PATH
而不是同名的函数。
因为至少在我的系统上scp
只支持短选项类型getopts
(也只支持短选项)就可以了。
该函数看起来像这样(未经测试):
scp () {
# wrapper function to prevent scp of local-only files
options=":346BCpqrTvc:F:i:J:l:o:P:S:"
while getopts $options option
do
case $option in
3 | 4 | 6 | B | C | p | q | r | T | v)
args+=($option)
;;
c | F | i | J | l | o | P | S)
args+=($option "$OPTARG")
;;
\? ) echo "Unknown option: -$OPTARG" >&2; return 1;;
: ) echo "Missing option argument for -$OPTARG" >&2; return 1;;
* ) echo "Unimplemented option: -$option" >&2; return 1;;
esac
done
shift $((OPTIND - 1))
if [[ $1 != *@*:* && $2 != *@*:* ]]
then
echo "Local-only copy not permitted"
echo "to override, use 'command scp ARGS'"
return 1
fi
command scp "${args[@]}" "$1" "$2"
}
此脚本中的选项反映了scp
撰写本文时所接受的选项,但它们可能会随时间而变化。这是此类包装器脚本所带来的风险之一。
答案2
我scp
使用常规cp
来复制本地文件。
创建一个名为的脚本cp
并确保scp
使用修改后的运行PATH
,以便找到该脚本而不是真正的脚本cp
。
脚本可能是这样的:
#!/bin/sh
echo 'Local copying unsupported!' >&2
exit 1
将其另存为~/.weird-stuff/cp
并使其可执行。然后创建一个名为的包装器scp
,修改PATH
真实的scp
。示例包装器函数:
scp () {
PATH="$HOME/.weird-stuff:$PATH" command scp "$@";
}
您可能更喜欢等效的包装脚本。
坏处:
- 无法保证 的未来版本
scp
将依赖cp
。如果scp
停止依赖cp
(或停止依赖PATH
来查找cp
),则解决方案将停止工作。
优势:
- 解决方案(不同于这个) 不需要理解 支持的选项
scp
。无论scp
命令行 如何解释,或者将来此事是否发生任何变化,只要scp
继续使用cp
进行本地复制(并PATH
查找cp
),该解决方案就会起作用。
答案3
低成本解决方案:如果如果您总是/经常从同一目录复制,并且总是/经常复制到同一主机,只需创建一个具有主机名称的假文件并删除其上的所有写权限:touch host && chmod ugo-w host
。然后您的错误 scp 命令将失败。