WinSCP同步时删除两边文件
WinSCP delete files on both sides when synchronizing
使用 WinSCP,有什么方法可以同步(在 SFTP 和本地目录之间)包括删除吗?
场景如下:如果文件存在于任何一侧而另一侧不存在,则应该创建它(synchronize both
就可以了)。如果某个文件在任一端被删除,则应在另一端将其删除。
我想我需要某种日志来跟踪文件何时被删除,在一侧或另一侧,以便可以在另一侧反映更改边.
如果我是对的,我认为 WinSCP 没有执行此操作的任何命令。有人做过吗?
WinSCP 做不到。它的同步是无状态的。对于您想要做的事情,您确实必须记住目录的先前状态。为了能够决定,是在一侧添加了不匹配的文件,还是在另一侧删除了不匹配的文件。
这对于普通 WinSCP scripting and a batch file. But with WinSCP .NET assembly from a PowerShell script, it is not that difficult. You can use the Session.CompareDirectories
method with the "both" mode 来说几乎是不可能的。对于 UploadNew
和 DownloadNew
的差异,在适当的时候将它们自定义为删除(使用缓存文件列表来决定)。
有 WinSCP 扩展 Two-Way Synchronization with Delete with SFTP/FTP server:
try
{
Add-Type -Path "WinSCPnet.dll"
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
Protocol = [WinSCP.Protocol]::Sftp
HostName = "example.com"
UserName = "user"
Password = "password"
SshHostKeyFingerprint = "ssh-rsa 2048 xxxxxxxxxxx...="
}
$localPath = "C:\local\path"
$remotePath = "/remote/path"
$previousFilesFile = "previous.txt"
if (Test-Path $previousFilesFile)
{
Write-Host "Loading list of previous local files..."
[string[]]$previousFiles = Get-Content $previousFilesFile
}
else
{
Write-Host "No list of previous local files"
$previousFiles = @()
}
$session = New-Object WinSCP.Session
try
{
# Connect
Write-Host "Connecting..."
$session.Open($sessionOptions)
$differences =
$session.CompareDirectories(
[WinSCP.SynchronizationMode]::Both, $localPath, $remotePath, $False)
if ($differences.Count -eq 0)
{
Write-Host "No changes found."
}
else
{
Write-Host "Synchronizing $($differences.Count) change(s)..."
foreach ($difference in $differences)
{
$action = $difference.Action
if ($action -eq [WinSCP.SynchronizationAction]::UploadNew)
{
if ($previousFiles -contains $difference.Local.FileName)
{
$path = $difference.Local.FileName
Write-Host "Removing local file $path..."
Remove-Item -Recurse $path
}
else
{
Write-Host "Uploading new $($difference.Local.FileName)..."
$difference.Resolve($session) | Out-Null
}
}
elseif ($action -eq [WinSCP.SynchronizationAction]::DownloadNew)
{
$localFilePath =
[WinSCP.RemotePath]::TranslateRemotePathToLocal(
$difference.Remote.FileName, $remotePath, $localPath)
if ($previousFiles -contains $localFilePath)
{
$path = $difference.Remote.FileName
Write-Host "Removing remote file $path..."
$path = [WinSCP.RemotePath]::EscapeFileMask($path)
$session.RemoveFiles($path).Check()
}
else
{
Write-Host "Downloading new $($difference.Remote.FileName)..."
$difference.Resolve($session) | Out-Null
}
}
elseif ($action -eq [WinSCP.SynchronizationAction]::DownloadUpdate)
{
Write-Host "Downloading updated $($difference.Remote.FileName)..."
$difference.Resolve($session) | Out-Null
}
elseif ($action -eq [WinSCP.SynchronizationAction]::UploadUpdate)
{
Write-Host "Uploading updated $($difference.Local.FileName)..."
$difference.Resolve($session) | Out-Null
}
else
{
throw "Unexpected difference $action"
}
}
}
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
Write-Host "Saving current local file list..."
$localFiles =
Get-ChildItem -Recurse -Path $localPath |
Select-Object -ExpandProperty FullName
Set-Content $previousFilesFile $localFiles
Write-Host "Done."
exit 0
}
catch
{
Write-Host "Error: $($_.Exception.Message)"
exit 1
}
使用 WinSCP,有什么方法可以同步(在 SFTP 和本地目录之间)包括删除吗?
场景如下:如果文件存在于任何一侧而另一侧不存在,则应该创建它(synchronize both
就可以了)。如果某个文件在任一端被删除,则应在另一端将其删除。
我想我需要某种日志来跟踪文件何时被删除,在一侧或另一侧,以便可以在另一侧反映更改边.
如果我是对的,我认为 WinSCP 没有执行此操作的任何命令。有人做过吗?
WinSCP 做不到。它的同步是无状态的。对于您想要做的事情,您确实必须记住目录的先前状态。为了能够决定,是在一侧添加了不匹配的文件,还是在另一侧删除了不匹配的文件。
这对于普通 WinSCP scripting and a batch file. But with WinSCP .NET assembly from a PowerShell script, it is not that difficult. You can use the Session.CompareDirectories
method with the "both" mode 来说几乎是不可能的。对于 UploadNew
和 DownloadNew
的差异,在适当的时候将它们自定义为删除(使用缓存文件列表来决定)。
有 WinSCP 扩展 Two-Way Synchronization with Delete with SFTP/FTP server:
try
{
Add-Type -Path "WinSCPnet.dll"
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
Protocol = [WinSCP.Protocol]::Sftp
HostName = "example.com"
UserName = "user"
Password = "password"
SshHostKeyFingerprint = "ssh-rsa 2048 xxxxxxxxxxx...="
}
$localPath = "C:\local\path"
$remotePath = "/remote/path"
$previousFilesFile = "previous.txt"
if (Test-Path $previousFilesFile)
{
Write-Host "Loading list of previous local files..."
[string[]]$previousFiles = Get-Content $previousFilesFile
}
else
{
Write-Host "No list of previous local files"
$previousFiles = @()
}
$session = New-Object WinSCP.Session
try
{
# Connect
Write-Host "Connecting..."
$session.Open($sessionOptions)
$differences =
$session.CompareDirectories(
[WinSCP.SynchronizationMode]::Both, $localPath, $remotePath, $False)
if ($differences.Count -eq 0)
{
Write-Host "No changes found."
}
else
{
Write-Host "Synchronizing $($differences.Count) change(s)..."
foreach ($difference in $differences)
{
$action = $difference.Action
if ($action -eq [WinSCP.SynchronizationAction]::UploadNew)
{
if ($previousFiles -contains $difference.Local.FileName)
{
$path = $difference.Local.FileName
Write-Host "Removing local file $path..."
Remove-Item -Recurse $path
}
else
{
Write-Host "Uploading new $($difference.Local.FileName)..."
$difference.Resolve($session) | Out-Null
}
}
elseif ($action -eq [WinSCP.SynchronizationAction]::DownloadNew)
{
$localFilePath =
[WinSCP.RemotePath]::TranslateRemotePathToLocal(
$difference.Remote.FileName, $remotePath, $localPath)
if ($previousFiles -contains $localFilePath)
{
$path = $difference.Remote.FileName
Write-Host "Removing remote file $path..."
$path = [WinSCP.RemotePath]::EscapeFileMask($path)
$session.RemoveFiles($path).Check()
}
else
{
Write-Host "Downloading new $($difference.Remote.FileName)..."
$difference.Resolve($session) | Out-Null
}
}
elseif ($action -eq [WinSCP.SynchronizationAction]::DownloadUpdate)
{
Write-Host "Downloading updated $($difference.Remote.FileName)..."
$difference.Resolve($session) | Out-Null
}
elseif ($action -eq [WinSCP.SynchronizationAction]::UploadUpdate)
{
Write-Host "Uploading updated $($difference.Local.FileName)..."
$difference.Resolve($session) | Out-Null
}
else
{
throw "Unexpected difference $action"
}
}
}
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
Write-Host "Saving current local file list..."
$localFiles =
Get-ChildItem -Recurse -Path $localPath |
Select-Object -ExpandProperty FullName
Set-Content $previousFilesFile $localFiles
Write-Host "Done."
exit 0
}
catch
{
Write-Host "Error: $($_.Exception.Message)"
exit 1
}