应用场景
针对文件夹内文件多,文件过于碎片化的传输,一次性无法完成的,每次重新传输,要么rsync对比过程极度漫长,要么只能从头开始,以下脚本支持直接跳过已传输内容,如要从头开始传,请删除/root/database.db,此文件路径可自行定义,确保执行的账号有访问权即可
解决方案:
本机内传输:
以下脚本均为shell格式,请自行复制后,赋予X权限
#!/bin/bash
# 数据库文件路径
base_file="/root/database.db"
# 源文件夹路径
source_directory="/root/a1"
# 目标文件夹路径
destination_directory="/root/b1"
# 检查数据库文件是否存在,如果不存在,则创建数据库文件和表格
if [ ! -f "$base_file" ]; then
# 创建数据库文件
sqlite3 "$base_file" <<- EOF
CREATE TABLE IF NOT EXISTS files (
id INTEGER PRIMARY KEY AUTOINCREMENT,
path TEXT,
is_transferred INTEGER DEFAULT 0,
md5sum TEXT
);
EOF
fi
# 处理文件传输函数
transfer_file() {
local source_file="$1"
local destination_dir="$2"
# 获取文件路径相对于源文件夹的相对路径
relative_path=${source_file#$source_directory}
# 检查文件是否已传输
is_transferred=$(sqlite3 "$" "SELECT is_transferred FROM files WHERE path='$relative_path';")
if [ -z "$is_transferred" ]; then
# 文件未传输,进行复制操作
cp "$source_file" "$destination_dir"
# 在目标文件夹中获取文件的MD5校验和
md5sum=$(md5sum "$destination_dir${relative_path}" | awk '{print $1}')
# 将文件路径、已传输标记和MD5校验和插入数据库
sqlite3 "$base_file" "INSERT INTO files (path, is_transferred, md5sum) VALUES ('$relative_path', 1, '$md5sum');"
# 输出已完成的标记
echo "Transferred: $relative_path"
else
# 文件已传输,跳过复制操作
echo "Skipped: $relative_path"
fi
}
# 打印所有文件名和MD5校验和
print_files() {
echo "文件名:MD5校验和"
# 查询数据库中的所有文件
files=$(sqlite3 "$base_file" "SELECT path, md5sum FROM files;")
# 逐行打印文件名和MD5校验和
while IFS="|" read -r path md5sum; do
echo "$path: $md5sum"
done <<< "$files"
}
# 递归处理源文件夹中的所有文件和子文件夹
process_directory() {
local source_dir="$1"
local destination_dir="$2"
# 遍历文件夹中的所有文件和子文件夹
for file in "$source_dir"/*
do
if [ -f "$file" ]; then
# 文件
transfer_file "$file" "$destination_dir"
elif [ -d "$file" ]; then
# 子文件夹
sub_directory="${file#$source_dir}"
# 在目标文件夹中创建子文件夹
mkdir -p "$destination_dir$sub_directory"
# 递归处理子文件夹
process_directory "$file" "$destination_dir$sub_directory"
fi
done
}
# 开始传输操作
echo "开始传输..."
process_directory "$source_directory" "$destination_directory"
echo "传输完成!"
# 打印所有文件名和MD5校验和
echo "文件名和MD5校验和:"
print_files
互联网或内网传输:
以下脚本均为shell格式,请自行复制后,赋予X权限
请配置免密或使用sshpass
#!/bin/bash
# 数据库文件路径
base_file="/root/database.db"
# 源文件夹路径
source_directory="/root/a1"
# 目标服务器信息
remote_server="root@192.168.137.11"
remote_directory="/root/b1/"
# 检查数据库文件是否存在,如果不存在,则创建数据库文件和表格
if [ ! -f "$base_file" ]; then
# 创建数据库文件
sqlite3 "$base_file" <<- EOF
CREATE TABLE IF NOT EXISTS files (
id INTEGER PRIMARY KEY AUTOINCREMENT,
path TEXT,
is_transferred INTEGER DEFAULT 0,
md5sum TEXT
);
EOF
fi
# 处理文件传输函数
transfer_file() {
local source_file="$1"
# 获取文件路径相对于源文件夹的相对路径
relative_path=${source_file#$source_directory}
# 检查文件是否已传输
is_transferred=$(sqlite3 "$base_file" "SELECT is_transferred FROM files WHERE path='$relative_path';")
if [ -z "$is_transferred" ]; then
# 文件未传输,进行复制操作
sshpass -p "11111111" scp "$source_file" "$remote_server:$remote_directory$relative_path"
# 在目标服务器中获取文件的MD5校验和
md5sum=$(sshpass -p "11111111" ssh "$remote_server" "md5sum $remote_directory$relative_path" | awk '{print $1}')
# 将文件路径、已传输标记和MD5校验和插入数据库
sqlite3 "$base_file" "INSERT INTO files (path, is_transferred, md5sum) VALUES ('$relative_path', 1, '$md5sum');"
# 输出已完成的标记
echo "Transferred: $relative_path"
else
# 文件已传输,跳过复制操作
echo "Skipped: $relative_path"
fi
}
# 打印所有文件名和MD5校验和
print_files() {
echo "文件名:MD5校验和"
# 查询数据库中的所有文件
files=$(sqlite3 "$base_file" "SELECT path, md5sum FROM files;")
# 逐行打印文件名和MD5校验和
while IFS="|" read -r path md5sum; do
echo "$path: $md5sum"
done <<< "$files"
}
# 获取文件数量
get_file_count() {
file_count=$(find "$source_directory" -type f | wc -l)
echo "$file_count"
}
# 递归处理源文件夹中的所有文件和子文件夹
process_directory() {
local source_dir="$1"
# 获取文件数量
total_files=$(get_file_count)
# 初始化已传输文件数
transferred_files=0
# 遍历文件夹中的所有文件和子文件夹
for file in "$source_dir"/*
do
if [ -f "$file" ]; then
# 文件
transfer_file "$file"
# 更新已传输文件数和剩余文件数
transferred_files=$((transferred_files + 1))
remaining_files=$((total_files - transferred_files))
# 显示传输进度
echo "Progress: $transferred_files/$total_files (Remaining: $remaining_files)"
elif [ -d "$file" ]; then
# 子文件夹
sub_directory="${file#$source_dir}"
# 递归处理子文件夹
process_directory "$file$sub_directory"
fi
done
}
# 开始传输操作
echo "开始传输..."
process_directory "$source_directory"
echo "传输完成!"
# 打印所有文件名和MD5校验和
echo "文件名和MD5校验和:"
print_files