Syncthing 文件版本控制

当集群中的文件被删除,或由更新版本替换时,Syncthing 可以归档文件的旧版本。这称为“文件版本控制”,可选择下文介绍的策略。版本控制按设备、按文件夹配置,默认不启用,也就是不保留文件的旧副本。

版本控制只适用于从其他设备接收的变更。例如,Alice 启用了版本控制,Bob 修改了文件,那么 Bob 的变更同步到 Alice 的电脑时,Alice 原有的文件版本会被归档。如果 Alice 在自己的电脑上修改本地文件,Syncthing 不会、也无法归档这个旧版本。

下面介绍各策略适用的配置选项。多数策略允许指定版本存储位置,默认是共享文件夹中的 .stversions 子文件夹。如果使用自定义位置,应确保它和普通文件夹位于同一分区或文件系统,否则移动文件可能失败。

回收站式版本控制

该策略模拟常见的“回收站”方式。远程设备的变更导致文件被删除或替换时,文件会移入 .stversions 文件夹中的回收站。如果里面已经有同名文件,旧的回收站文件会被替换。

可以用 cleanoutDays 配置清理超过指定天数的文件。如果设置为正数,文件在回收站存放这么多天后会被删除。设为 0 则不自动删除回收站中的文件。

简单版本控制

当远程设备替换或删除文件时,“简单版本控制”同样把文件移入 .stversions。除了 cleanoutDays,该策略还提供 Keep Versions(保留版本数) 输入项,用于指定每个文件要保留多少个旧版本,对应 keep 配置。

例如,设为 5 后,如果文件在远程设备被替换了五次,共享同一文件夹的其他设备中的 .stversions 会保留该文件五个带时间戳的版本。

分层保留版本

“分层保留版本”同样在远程设备替换或删除文件时,把文件移入 .stversions,与简单版本控制相似。不过,超过最大保留时间,或超过某个时间区间允许数量的版本,会被自动删除。

采用以下时间区间,每个区间分别限制保留的版本数量:

文件版本的年龄 保留规则
最初一小时 每30秒区间保留最旧的一个版本
最初一天 每小时区间保留最旧的一个版本
最初30天 每天区间保留最旧的一个版本
之后直到最大保留时间 每周区间保留最旧的一个版本

Maximum Age(最大保留时间) 在界面中以天为单位。例如,要把被替换或删除的文件保留一年,使用 365;只保留十天,使用 10。它对应 maxAge,设为 0 表示永久保留。

这意味着每个区间只保留一个版本。随着文件版本变旧,除非它将要进入的区间为空,否则会被删除。保留每个区间最旧的版本,可以在文件被覆盖时保留之前的内容。

具体一次运行会删除哪些版本,可参阅原文链接的单元测试。

外部版本控制

该策略把处理文件的决定交给一个外部命令,例如程序或命令行脚本。文件即将被替换之前,Syncthing 会执行该命令。命令必须在处理过程中把文件从同步文件夹中移走,否则 Syncthing 会报错。

命令可以使用以下模板参数或环境变量:

模板参数 环境变量 含义
%FOLDER_PATH% $FOLDER_PATH Syncthing文件夹的路径
%FILE_PATH% $FILE_PATH 文件在该文件夹内的相对路径

前者展开为实际 Syncthing 文件夹路径,后者展开为文件夹内部路径。例如,Windows 默认 Sync 文件夹中的文件完整路径是 C:\Users\User\Sync\Family photos\IMG_2021-03-01.jpg,那么 %FOLDER_PATH% 为 C:\Users\User\Sync,%FILE_PATH% 为 Family photos\IMG_2021-03-01.jpg。

文件路径应当视为不可信用户输入,不能假定它不包含恶意字符或命令。

Syncthing 会确保未加引号的模板变量作为独立参数传入,例如 somecommand %FOLDER_PATH% %FILE_PATH%。未加引号的组合 %FOLDER_PATH%/%FILE_PATH% 也有效。

任何形式的 shell 包装,例如 sh -c "echo %FOLDER_PATH%/%FILE_PATH%",均无效,Syncthing 可能因安全原因拒绝这样的命令。

2.1.2版本新增: 环境变量 $FOLDER_PATH 和 $FILE_PATH,脚本可用它们代替命令行模板占位符。

Unix 示例

假设希望在文件被替换或删除时只保留最近一个旧版本,也就是类似回收站的行为。创建下面的脚本,保存为 /Users/jb/bin/onlylatest.sh,即主目录中的 bin 文件夹:

#!/bin/sh
set -eu

# Where I want my versions stored
versionspath=~/.trashcan

# The parameters we get from Syncthing
folderpath="$1"
filepath="$2"
# First ensure the dir where we need to store the file exists
outpath=$(dirname "$versionspath/$filepath")
mkdir -p "$outpath"
# Then move the file there
mv -f "$folderpath/$filepath" "$versionspath/$filepath"

确保脚本具有执行权限:

chmod 755 onlylatest.sh

然后在 Syncthing 中配置命令:

/Users/jb/bin/onlylatest.sh %FOLDER_PATH% %FILE_PATH%

假设 ~/Sync 中有一个名为“default”的文件夹,里面的 docs/letter.txt 即将被替换或删除,脚本的调用等同于:

/Users/jb/bin/onlylatest.sh /Users/jb/Sync docs/letter.txt

脚本将把文件移到 ~/.trashcan/docs/letter.txt,替换那里已有的该文件版本。

Windows 示例

使用命令提示符(CMD)移入指定文件夹

在 Windows 上,可用批处理脚本实现相同的回收站式行为。下面的脚本保存为 C:\Users\mfrnd\Scripts\onlylatest.bat:

@echo off

rem Enable UTF-8 encoding to deal with multilingual folder and file names
chcp 65001

rem We need command extensions for md to create intermediate folders in one go
setlocal enableextensions

rem Where I want my versions stored
set "versions_path=%USERPROFILE%\.trashcan"

rem The parameters we get from Syncthing, '~' removes quotes if any
set "folder_path=%~1"
set "file_path=%~2"

rem First ensure the dir where we need to store the file exists
for %%f in ("%versions_path%\%file_path%") do set "output_path=%%~dpf"
if not exist "%output_path%" md "%output_path%" || exit /b

rem Finally move the file, overwrite existing file if any
move /y "%folder_path%\%file_path%" "%versions_path%\%file_path%"

在 Syncthing 中将命令配置为:

"C:\Users\mfrnd\Scripts\onlylatest.bat" "%FOLDER_PATH%" "%FILE_PATH%"

使用 PowerShell 移入回收站

PowerShell 可以把文件直接送入回收站,模拟资源管理器的删除行为。先创建以下脚本,保存到所需位置,例如 C:\Users\User\Scripts\SendToRecycleBin.ps1:

# PowerShell has no native method to recycle files, so we use Visual
# Basic to perform the operation. If succeeded, we also include the
# recycled file in the Syncthing's DEBUG output.
Add-Type -AssemblyName Microsoft.VisualBasic
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile($args,'OnlyErrorDialogs','SendToRecycleBin')
if ($?) {
  Write-Output ("Recycled " + $args + ".")
}

也可以扩展脚本,只把删除的文件送入回收站,对修改前的旧文件直接永久删除,使其更接近资源管理器的行为:

# PowerShell has no native method to recycle files, so we use Visual
# Basic to perform the operation.
Add-Type -AssemblyName Microsoft.VisualBasic

# We need to test if a Syncthing .tmp file exists. If it does, we assume
# a modification and delete the existing file. If if does not, we assume
# a deletion and recycle the current file. If succeeded, we also include
# the deleted/recycled file in the Syncthing's DEBUG output.
if (Test-Path -LiteralPath ((Split-Path -Path $args) + "\~syncthing~" + (Split-Path -Path $args -Leaf) + ".tmp")) {
  [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile($args,'OnlyErrorDialogs','DeletePermanently')
  if ($?) {
    Write-Output ("Deleted " + $args + ".")
  }
} else {
  [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile($args,'OnlyErrorDialogs','SendToRecycleBin')
  if ($?) {
    Write-Output ("Recycled " + $args + ".")
  }
}

最后,在 Syncthing 中配置:

powershell.exe -ExecutionPolicy Bypass -File "C:\Users\User\Scripts\SendToRecycleBin.ps1" "%FOLDER_PATH%\%FILE_PATH%"

需要注意:如果同步文件夹位于USB存储等可移动介质,或者系统禁用了回收站,上述脚本最终会永久删除文件。

配置参数参考

版本控制设置位于配置文件中各文件夹独立的配置区段内。例如:

<folder id="...">
    <versioning type="simple">
        <cleanupIntervalS>3600</cleanupIntervalS>
        <fsPath></fsPath>
        <fsType>basic</fsType>
        <param key="cleanoutDays" val="0"></param>
        <param key="keep" val="5"></param>
    </versioning>
</folder>

versioning.type

选择策略:trashcan、simple、staggered 或 external。留空表示完全禁用版本控制。

versioning.fsPath

覆盖旧版本的存储路径。留空时默认为 .stversions。可以指定绝对或相对路径。如果 fsType 为 basic,相对路径以共享文件夹为基准。external 策略忽略该选项。

该选项过去位于 params 元素中的 fsPath 或 versionsPath 键下。

versioning.fsType

用于访问版本文件夹的内部文件系统实现。只有 fsPath 非空时才适用;否则使用 folder 元素的 filesystemType。可用值参见文件夹配置。external 策略忽略此项。

该选项过去位于 params 元素的 fsType 键下。

versioning.cleanupIntervalS

版本文件夹执行清理的间隔,单位为秒。0 表示禁用定期清理,最大为一年,即 31536000 秒。external 策略忽略此项。

该选项过去位于 params 元素的 cleanInterval 键下。

versioning.params

各版本控制策略专用的参数位于此元素下。

versioning.params.cleanoutDays

版本文件夹中的文件保留天数。0 表示永久保留。清理时遇到超过保留时间的条目就会删除。

versioning.params.keep

每个文件保留的旧版本数量。

versioning.params.maxAge

保留版本的最大时间,单位为秒。0 表示永久保留。

这里是配置文件的秒数;上面的界面“Maximum Age”使用天数,二者不能直接混用。

versioning.params.command

用于保存即将被替换或删除文件版本的外部命令。如果应用程序路径包含空格,应给它加引号。


来源:File Versioning,Syncthing文档贡献者。核对日期:2026-10-03。原页标记版本为 v2.1.0-24-g1f79d9e,同时明确列出2.1.2新增环境变量;使用时应按目标版本确认支持情况。

文档和协议规格采用 CC BY 4.0,依据官方文档仓库许可声明。改动:完整中文翻译、整理表格与代码排版,补充界面天数和配置秒数的区别。所有脚本、命令、XML及代码注释保留原文,不宣称在本环境运行或实测。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容