You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash脚本从SSH远程主机复制倒数第二个文件至本地报错求助

问题原因

你遇到的scp: .: not a regular file错误,核心原因是本地脚本无法获取远程SSH会话里的变量值:

  • 你的SSH heredoc用了'ENDSSH',这段代码完全在远程主机B执行,pathFile和zipFile都是远程环境的变量,本地脚本根本拿不到它们的值。
  • 执行scp时,$pathFile和$zipFile是空的,导致scp的源路径变成$userName@machineB::,实际对应远程主机的当前目录。而scp默认不支持复制目录(需加-r参数),所以报错说.(当前目录)不是常规文件。
修复后的脚本

下面是修正后的脚本,核心思路是把远程获取的文件名传递回本地变量,再执行scp:

#!/bin/bash

# 用$()替代反引号,更易读且支持嵌套
userName=$(whoami)
myLocation=$(pwd)

# 远程执行命令,获取倒数第二个文件的文件名,并传递回本地
remote_filename=$(ssh "$userName@machineB" '
remote_path="/somefolder/folder_1/businessfolder/"
# 切换目录失败则直接退出,避免后续命令出错
cd "$remote_path" || exit 1
# 用ls -1tr确保每个文件名单独一行,按修改时间升序排列后取倒数第二个
ls -1tr | tail -n 2 | head -1
')

# 检查是否成功获取文件名
if [ -z "$remote_filename" ]; then
    echo "错误:未能获取到远程主机的目标文件"
    exit 1
fi

# 执行scp,注意用双引号包裹变量,避免文件名含空格/特殊字符时出错
scp "$userName@machineB:/somefolder/folder_1/businessfolder/$remote_filename" "$myLocation"
更可靠的优化方案(避免ls解析文件名的坑)

用ls解析文件名存在隐患(比如文件名含空格、换行或特殊字符时会出错),推荐用find命令更稳定地获取目标文件:

#!/bin/bash

userName=$(whoami)
myLocation=$(pwd)

remote_filename=$(ssh "$userName@machineB" '
remote_path="/somefolder/folder_1/businessfolder/"
# 查找目录下的普通文件,输出修改时间戳+文件名,按时间戳排序后取倒数第二个
find "$remote_path" -maxdepth 1 -type f -printf "%T@ %f\n" | sort -n | tail -n 2 | head -1 | cut -d" " -f2-
')

if [ -z "$remote_filename" ]; then
    echo "错误:未能获取到远程主机的目标文件"
    exit 1
fi

scp "$userName@machineB:/somefolder/folder_1/businessfolder/$remote_filename" "$myLocation"
  • find的%T@输出文件的修改时间戳(精确到秒),结合sort -n按时间升序排列,确保排序逻辑准确。
  • cut -d" " -f2-用来分离时间戳和文件名,即使文件名含空格也能正确提取。

内容的提问来源于stack exchange,提问作者CrazyCat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 05:05:16