本文目录导读:

- 方法1:使用 pv 命令(推荐)
- 方法2:使用 rsync + 进度条
- 方法3:使用 bar 或 dialog 工具
- 方法4:使用 expect 脚本(高级)
- 方法5:使用 Python 脚本(最灵活)
- 安装必要工具
- 完整示例脚本
- 推荐方案
在 Shell 脚本中使用 SCP 传输并显示进度条,有几种常见方法,以下是完整的解决方案:
方法1:使用 pv 命令(推荐)
pv 是一个专门用于监控数据通过管道的工具,可以显示进度条。
#!/bin/bash # 定义源文件和目标 SOURCE_FILE="/path/to/large/file.zip" TARGET_USER="user" TARGET_HOST="192.168.1.100" TARGET_PATH="/home/user/" # 使用 pv 显示进度 pv "$SOURCE_FILE" | ssh "$TARGET_USER@$TARGET_HOST" "cat > $TARGET_PATH$(basename $SOURCE_FILE)" # 或者使用 scp + pv(需要知道文件大小) FILE_SIZE=$(stat -c%s "$SOURCE_FILE") pv -s "$FILE_SIZE" "$SOURCE_FILE" | ssh "$TARGET_USER@$TARGET_HOST" "cat > $TARGET_PATH$(basename $SOURCE_FILE)"
方法2:使用 rsync + 进度条
rsync 原生支持进度条显示:
#!/bin/bash SOURCE_FILE="/path/to/large/file.zip" TARGET="user@192.168.1.100:/home/user/" # 使用 rsync 显示进度 rsync -P --progress "$SOURCE_FILE" "$TARGET" # 参数说明: # -P 等同于 --partial --progress # --progress 显示传输进度
方法3:使用 bar 或 dialog 工具
创建一个自定义进度条函数:
#!/bin/bash
# 自定义进度条函数
show_progress() {
local current=$1
local total=$2
local width=50
# 计算百分比
local percent=$((current * 100 / total))
local completed=$((width * current / total))
# 构建进度条
printf "\r["
for ((i=0; i<width; i++)); do
if [ $i -lt $completed ]; then
printf "="
else
printf " "
fi
done
printf "] %d%%" $percent
}
# 模拟 SCP 传输(实际使用需要配合 expect 或其他工具)
# 这里仅演示进度条函数
for ((i=0; i<=100; i+=5)); do
show_progress $i 100
sleep 0.1
done
echo ""
方法4:使用 expect 脚本(高级)
对于需要完全自动化的场景:
#!/usr/bin/expect -f
set timeout -1
set source "/path/to/file.zip"
set target "user@192.168.1.100:/home/user/"
spawn scp -v "$source" "$target"
expect {
"password:" {
send "your_password\r"
exp_continue
}
-re {(\d+)%} {
set progress $expect_out(1,string)
send_user "\rProgress: $progress%"
exp_continue
}
eof
}
方法5:使用 Python 脚本(最灵活)
#!/usr/bin/env python3
import subprocess
import sys
import os
def scp_with_progress(source, target, password=None):
# 获取文件大小
file_size = os.path.getsize(source)
# 构建 scp 命令
cmd = ['scp', '-v', source, target]
# 启动进程
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True
)
# 实时读取输出
while True:
output = process.stderr.readline()
if output == '' and process.poll() is not None:
break
if output:
# 解析百分比
if '%' in output:
try:
percent = output.split('%')[0].strip().split()[-1]
# 显示进度条
sys.stdout.write(f'\r传输进度: {percent}%')
sys.stdout.flush()
except:
pass
print("\n传输完成!")
# 使用示例
scp_with_progress('/path/to/file.zip', 'user@192.168.1.100:/home/user/')
安装必要工具
# Ubuntu/Debian sudo apt-get install pv rsync # CentOS/RHEL sudo yum install pv rsync # macOS brew install pv rsync
完整示例脚本
这是一个完整的带进度条的 SCP 传输脚本:
#!/bin/bash
# 显示帮助信息
usage() {
echo "用法: $0 <源文件> <目标>"
echo "示例: $0 /path/to/file.zip user@host:/path/"
exit 1
}
# 检查参数
if [ $# -ne 2 ]; then
usage
fi
SOURCE="$1"
TARGET="$2"
# 检查源文件是否存在
if [ ! -f "$SOURCE" ]; then
echo "错误: 文件 $SOURCE 不存在"
exit 1
fi
# 获取文件大小
FILE_SIZE=$(stat -c%s "$SOURCE" 2>/dev/null || stat -f%z "$SOURCE" 2>/dev/null)
# 检查 pv 是否安装
if command -v pv &> /dev/null; then
echo "使用 pv 显示进度条..."
pv -s "$FILE_SIZE" "$SOURCE" | ssh "${TARGET%%:*}" "cat > ${TARGET#*:}/$(basename $SOURCE)"
elif command -v rsync &> /dev/null; then
echo "使用 rsync 显示进度条..."
rsync -P --progress "$SOURCE" "$TARGET"
else
echo "使用 scp (无进度条)..."
scp "$SOURCE" "$TARGET"
fi
echo "传输完成!"
推荐方案
- 最简单:使用
rsync -P或rsync --progress - 最灵活:使用
pv工具 - 最可控:自定义 Python/Expect 脚本
选择哪种方法取决于你的具体需求和系统环境。