仅用echo、cat与here-document通过SSH传输文件时出现异常
问题根源
- 本地Shell提前解析变量:你使用无引号的
EOF1作为here-document分界符,本地Bash会先展开$w——将文件里的换行替换成空格,同时文件中的!会触发历史命令扩展,导致远程执行的echo $w因语法错误直接失败,没有写入任何内容。 echo无法处理多行内容:即便变量展开正常,echo默认会把连续空白(包括换行)压缩为空格,无法完整保留原文件的多行格式。
修复方法
方法一:带单引号的here-document+cat传递完整内容(推荐)
不需要中间变量,通过嵌套here-document把本地文件内容传给远程cat,完整保留换行和特殊字符:
#!/bin/bash SSH_CMD=xxx # 替换为你的实际SSH命令 $SSH_CMD <<'REMOTE_CMD' cd /data00 # 嵌套here-document让远程cat接收本地文件内容 cat >> for-test <<'LOCAL_CONTENT' $(cat word) LOCAL_CONTENT echo "abc" >> for-test REMOTE_CMD
说明:LOCAL_CONTENT区域会被本地Bash替换为word文件的实际内容,REMOTE_CMD加单引号避免本地解析远程命令里的变量。
方法二:关闭历史扩展+双引号包裹变量
先关闭Bash的历史扩展避免!字符报错,再用双引号包裹变量确保远程echo输出完整多行内容:
#!/bin/bash SSH_CMD=xxx # 替换为你的实际SSH命令 # 关闭历史扩展,防止文件中的!触发错误 set +o histexpand # 读取本地文件内容到变量,保留换行 w=$(cat word) # 无引号的EOF允许本地展开$w,远程用双引号包裹确保多行保留 $SSH_CMD <<EOF cd /data00 touch for-test echo "$w" >> for-test echo "abc" >> for-test EOF # 恢复历史扩展(可选) set -o histexpand
方法三:管道直接传输(最简)
如果允许用管道(你提到可以用cat),直接把本地cat的输出传给远程cat,比here-document更简洁:
#!/bin/bash SSH_CMD=xxx # 替换为你的实际SSH命令 # 传输本地文件内容到远程 cat word | $SSH_CMD 'cat >> /data00/for-test' # 追加abc内容 $SSH_CMD 'echo "abc" >> /data00/for-test'
内容的提问来源于stack exchange,提问作者LimingFang
相关产品推荐
相关产品推荐

