gpt4 book ai didi

powershell - PowerShell 可以使用 FTP 在一次传输中检索远程文件夹和子文件夹目录数据吗?

转载 作者:行者123 更新时间:2023-12-02 23:39:00 25 4
gpt4 key购买 nike

我有一个 PowerShell 脚本,用于检查远程位置文件的现有时间戳数据,以与本地文件进行比较。

使用以下代码段检索本地信息:

$SrcEntries = Get-ChildItem $FolderLocation -Recurse

然后,我可以使用以下代码段获取有关文件夹和文件的特定信息:
$Srcfolders = $SrcEntries | Where-Object{$_.PSIsContainer}
$SrcFiles = $SrcEntries | Where-Object{!$_.PSIsContainer}

当前使用此代码段检索远程信息,该代码段为每个文件单独执行:
$Credentials = New-Object System.Net.NetworkCredential($FTPUser,$FTPPassword)
$FTPrequest = [System.Net.FtpWebRequest]::Create($RemoteFilePath)
$FTPrequest.Method = [System.Net.WebRequestMethods+FTP]::GetDateTimestamp
$FTPrequest.Credentials = $Credentials
$response = $FTPrequest.GetResponse().StatusDescription
$response然后解析以检索远程文件的时间戳。

以与检索本地数据相同的方式检索远程数据似乎更好,即在单个操作中与上面的第一个片段一样,以避免多次往返远程服务器。

是否可以使用 PowerShell 在单个快速 FTP 操作中递归地获取文件夹和文件目录数据?我该怎么做?

最佳答案

没有任何外部库,要实现这一点并不容易。不幸的是,.NET Framework 和 PowerShell 都没有明确支持在 FTP 文件夹中递归列出文件。
您必须自己实现:

  • 列出远程文件夹
  • 迭代条目,递归到子文件夹 - 再次列出它们,等等。

  • 第一个棘手的部分是从子文件夹中识别文件。使用 .NET 框架 ( FtpWebRequest) 无法以可移植的方式做到这一点。不幸的是,.NET 框架不支持 MLSD命令,这是在 FTP 协议(protocol)中检索具有文件属性的目录列表的唯一可移植方式。另见 Checking if object on FTP server is file or directory .
    您的选择是:
  • 对文件名执行操作,对于文件肯定会失败,而对于目录会成功(反之亦然)。 IE。您可以尝试下载“名称”。
  • 您可能很幸运,在您的特定情况下,您可以通过文件名来区分目录中的文件(即所有文件都有扩展名,而子目录没有)
  • 您使用长目录列表(LIST 命令 = ListDirectoryDetails 方法)并尝试解析特定于服务器的列表。许多 FTP 服务器使用 *nix 样式的列表,您可以在其中通过 d 标识目录。在条目的最开始。但是许多服务器使用不同的格式。以下示例使用此方法(假设 *nix 格式)
  • function ListFtpDirectory($url, $credentials)
    {
    $listRequest = [Net.WebRequest]::Create($url)
    $listRequest.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails
    $listRequest.Credentials = $credentials

    $lines = New-Object System.Collections.ArrayList

    $listResponse = $listRequest.GetResponse()
    $listStream = $listResponse.GetResponseStream()
    $listReader = New-Object System.IO.StreamReader($listStream)
    while (!$listReader.EndOfStream)
    {
    $line = $listReader.ReadLine()
    $lines.Add($line) | Out-Null
    }
    $listReader.Dispose()
    $listStream.Dispose()
    $listResponse.Dispose()

    foreach ($line in $lines)
    {
    $tokens = $line.Split(" ", 9, [StringSplitOptions]::RemoveEmptyEntries)
    $name = $tokens[8]
    $permissions = $tokens[0]

    if ($permissions[0] -eq 'd')
    {
    Write-Host "Directory $name"

    $fileUrl = ($url + $name)
    ListFtpDirectory ($fileUrl + "/") $credentials
    }
    else
    {
    Write-Host "File $name"
    }
    }
    }
    使用如下功能:
    $credentials = New-Object System.Net.NetworkCredential("user", "mypassword") 
    $url = "ftp://ftp.example.com/directory/to/list/"
    ListFtpDirectory $url $credentials

    虽然上面的代码将只列出名称。由于您也需要时间戳,因此您甚至必须解析这些时间戳。这就像确定一个条目是文件夹还是文件一样复杂。
    我没有 PowerShell 代码,但请参阅我对其他类似问题的回答,其中显示了 C# 代码。翻译成 PowerShell 应该很容易:
  • Retrieving creation date of file (FTP)
  • Parsing FtpWebRequest ListDirectoryDetails line
  • C# class to parse WebRequestMethods.Ftp.ListDirectoryDetails FTP response

  • 如果您想避免解析服务器特定目录列表格式的麻烦,请使用支持 MLSD 的第 3 方库。命令和/或解析各种 LIST列表格式。
    例如 WinSCP .NET assembly您可以通过调用 Session.EnumerateRemoteFiles 递归地列出整个目录:
    # Load WinSCP .NET assembly
    Add-Type -Path "WinSCPnet.dll"

    # Setup session options
    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
    Protocol = [WinSCP.Protocol]::Ftp
    HostName = "ftp.example.com"
    UserName = "user"
    Password = "mypassword"
    }

    $session = New-Object WinSCP.Session

    try
    {
    # Connect
    $session.Open($sessionOptions)

    # Download files
    $options =
    [WinSCP.EnumerationOptions]::EnumerateDirectories -bor
    [WinSCP.EnumerationOptions]::AllDirectories
    $fileInfos = $session.EnumerateRemoteFiles(
    "/directory/to/list", $Null, $options)
    foreach ($fileInfo in $fileInfos)
    {
    Write-Host $fileInfo.FullName
    }
    }
    finally
    {
    # Disconnect, clean up
    $session.Dispose()
    }
    不仅代码更简单,更健壮且独立于平台。它还使所有其他文件属性(大小、修改时间、权限、所有权)通过 RemoteFileInfo class 随时可用。 .
    在内部,WinSCP 使用 MLSD命令(如果服务器支持)。如果没有,它使用 LIST命令并支持数十种不同的列表格式。

    尽管您似乎旨在比较本地和远程时间戳以同步文件夹。
    WinSCP .NET 程序集可以通过使用 Session.SynchronizeDirectories 的单个调用来完成。 .
    您可能还会发现这些问题(由我回答)很有用:
  • How to compare age of local file with file on FTP server and download if remote copy is newer in PowerShell
  • How do I query a file on FTP server in PowerShell to determine if an upload is required?

  • (我是WinSCP的作者)

    关于powershell - PowerShell 可以使用 FTP 在一次传输中检索远程文件夹和子文件夹目录数据吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47478230/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com