Цель: я пытаюсь получить все файлы старше 1 дня. Удаленный каталог имеет множество каталогов, а также файлы в корневом каталоге.
Мне нужно заглянуть в каждый каталог, получить любые файлы возрастом 1 день, а также любой файл в корневом каталоге возрастом 1 день и перенести их все в один каталог. Я бы не хотел копировать пустые каталоги или каталоги с файлами старше 1 дня.
Текущий код просто продолжает работать и не передает никаких файлов. Я не уверен, правильно ли я настроил раздел foreach
, а также раздел GetFiles
.
Что должен сказать раздел GetFiles
, чтобы соответствовать требованиям к файлам, перечисленным выше?
Вот пример того, как это выглядит:
Код:
# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"
# Set up session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
Protocol = [WinSCP.Protocol]::ftp
HostName = "ftp site"
UserName = "UserName"
Password = "Password"
SshHostKeyFingerprint = "stuff"
}
$sessionOptions.AddRawSettings("FSProtocol", "2")
$session = New-Object WinSCP.Session
$session.SessionLogPath = $log
try {
# Connect
$session.Open($sessionOptions)
# Set up transfer options
$transferOptions = New-Object WinSCP.TransferOptions -Property @{
TransferMode = [WinSCP.TransferMode]::Ascii
}
$lcdPath = 'Filepath\'
$time = (Get-Date).AddDays(-1)
$files = @(Get-ChildItem -Path $lcdPath -Attributes !Directory -Recurse | Where-Object { $_.LastWriteTime -gt $time })
# Transfer files
foreach ($file in $files) {
$session.GetFiles($files, "LocalFilePath", $False, $transferOptions).Check()
}
}
finally {
$session.Dispose()
}
exit 0
catch
{
Write-Host "Error: $($_.Exception.Message)"
exit 1
}
У вас есть пара проблем, и ваш код потребует некоторой доработки, но вы закроете.
Ваша самая большая проблема заключается в том, что вы ищете новые файлы в Filepath\
в текущем каталоге вашей локальной файловой системы, а не на FTP-сервере:
$files = @(Get-ChildItem -Path $lcdPath -Attributes !Directory -Recurse | Where-Object { $_.LastWriteTime -gt $time })
Я думаю, вы хотите перечислить удаленные файлы на FTP-сервере и вместо этого построить свой $files
список из этих данных. (пример ниже взят с сайта winscp.net)
$session.Open($sessionOptions)
$directory = $session.ListDirectory("/home/martin/public_html")
foreach ($fileInfo in $directory.Files)
{
Write-Host ("$($fileInfo.Name) with size $($fileInfo.Length), " +
"permissions $($fileInfo.FilePermissions) and " +
"last modification at $($fileInfo.LastWriteTime)")
}
Вы можете адаптировать этот код для заполнения вашего массива $files
на основе $fileinfo.LastWriteTime
удаленных файлов, а затем передать его в цикл foreach «Передача файлов».
Также у вас есть проблемы с синтаксисом в коде try/catch/finally, он должен выглядеть так:
catch
{
Write-Host "Error: $($_.Exception.Message)"
exit 1
}
finally {
$session.Dispose()
}
exit 0
Кроме того, я ценю помощь в решении логической ошибки поиска в локальном каталоге вместо каталога FTP.
ListDirectory будет отображать только содержимое указанного каталога. Вместо этого вы можете выполнить рекурсивный поиск с помощью Session.EnumerateRemoteFiles
. Я бы посоветовал вам определить перед циклом foreach $files = @()
(пустой массив), затем внутри foreach вы можете проверить каждый файл, чтобы подтвердить, что LastWriteTime
, Length
и т. д. соответствуют вашим критериям, и добавить удаленный путь к вашему массиву $files
. Взгляните на приведенные здесь примеры: winscp.net/eng/docs/…
Спасибо за всю твою помощь. Мне не удалось заставить Session.enumerateRemoteFiles работать, поэтому я выбрал другой путь, я добавлю его в качестве ответа на случай, если он будет полезен другим.
Вот пример сайта WinSCP, который реализует часть того, чего вы хотите достичь:
Загрузка всех файлов с FTP/SFTP в одну и ту же локальную папку.
Вам просто нужно добавить условие времени, для которого вы можете проверить:
Загружайте файлы новее X дней с SFTP-сервера с помощью WinSCP, пропуская папки, не содержащие подходящих файлов
Объединив их вместе, это должно сделать:
$remotePath = "/remote/path"
$localPath = "C:\local\path"
$mask = "*.txt"
$files = $session.EnumerateRemoteFiles(
$remotePath, $mask, [WinSCP.EnumerationOptions]::AllDirectories)
$limit = (Get-Date).AddDays(-1)
$files = $files | Where-Object { $_.LastWriteTime -gt $limit }
foreach ($fileInfo in $files)
{
Write-Host "Downloading $($fileInfo.FullName) ..."
$session.GetFileToDirectory($fileInfo.FullName, $localPath)
}
Спасибо @MisterSmith! Я благодарен за вашу помощь! Я исправил свой улов и возвращаю файлы с кодом, с которым вы мне помогли! Мне нужно изменить его, чтобы извлекать только файлы размером больше 0 и изменять их только за последний 1 день. Должен ли я фильтровать это в самом выражении ForEach или внутри ForEach? Мне просто нужно рекурсивно захватить только файлы из корня. Я изменил одну часть кода, чтобы получить данные из корня FTP-сайта: $directory = $session.ListDirectory("/")