Загрузите однодневные старые файлы из всех каталогов FTP в один локальный каталог с помощью сборки WinSCP .NET

Цель: я пытаюсь получить все файлы старше 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
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
146
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

У вас есть пара проблем, и ваш код потребует некоторой доработки, но вы закроете.

Ваша самая большая проблема заключается в том, что вы ищете новые файлы в 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

Спасибо @MisterSmith! Я благодарен за вашу помощь! Я исправил свой улов и возвращаю файлы с кодом, с которым вы мне помогли! Мне нужно изменить его, чтобы извлекать только файлы размером больше 0 и изменять их только за последний 1 день. Должен ли я фильтровать это в самом выражении ForEach или внутри ForEach? Мне просто нужно рекурсивно захватить только файлы из корня. Я изменил одну часть кода, чтобы получить данные из корня FTP-сайта: $directory = $session.ListDirectory("/")

JM1 27.10.2022 13:49

Кроме того, я ценю помощь в решении логической ошибки поиска в локальном каталоге вместо каталога FTP.

JM1 27.10.2022 13:55

ListDirectory будет отображать только содержимое указанного каталога. Вместо этого вы можете выполнить рекурсивный поиск с помощью Session.EnumerateRemoteFiles. Я бы посоветовал вам определить перед циклом foreach $files = @() (пустой массив), затем внутри foreach вы можете проверить каждый файл, чтобы подтвердить, что LastWriteTime, Length и т. д. соответствуют вашим критериям, и добавить удаленный путь к вашему массиву $files. Взгляните на приведенные здесь примеры: winscp.net/eng/docs/…

MisterSmith 27.10.2022 18:39

Спасибо за всю твою помощь. Мне не удалось заставить Session.enumerateRemoteFiles работать, поэтому я выбрал другой путь, я добавлю его в качестве ответа на случай, если он будет полезен другим.

JM1 28.10.2022 19:39
Ответ принят как подходящий

Вот пример сайта 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) 
}

Другие вопросы по теме