Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
747 views
in Technique[技术] by (71.8m points)

.net - Delete files older than X days from FTP server with PowerShell or batch file

I have to write a script which accesses an FTP server, and then deletes all *.zip files which are older than X days.

As clarification: The script can't run on the FTP server.

This is what I have so far:

$ftpServer = "RandomFTPServer"
$ftpUser = "Username"
$ftpPassword = Read-Host "Password" -AsSecureString

$credentials = New-ObjectSystem.Net.NetworkCredential($ftpUser, $ftpPassword)

function Get-FtpRequest($ftpPath) {
    $ftpRequest = [System.Net.FtpWebRequest]::Create("$ftpServer/$ftpPath")
    $ftpRequest.Credentials = $credentials
    $ftpRequest.UseBinary = $true 
    $ftpRequest.KeepAlive = $true
    $ftpRequest.UsePassive = $true
    return $ftpRequest
}

Any tips on what I need to do next?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have to retrieve timestamps of remote files to select the old ones.

Unfortunately, there's no really reliable and efficient way to retrieve timestamps using features offered by .NET framework/PowerShell as it does not support FTP MLSD command.

So either you use:

  • ListDirectoryDetails method (FTP LIST command) to retrieve details of all files in a directory and then you deal with FTP server specific format of the details (*nix format similar to ls *nix command is the most common, drawback is that the format may change over time, as for newer files "May 8 17:48" format is used and for older files "Oct 18 2009" format is used)
  • GetDateTimestamp method (FTP MDTM command) to individually retrieve timestamps for each file. Advantage is that the response is standardized by RFC 3659 to YYYYMMDDHHMMSS[.sss]. Disadvantage is that you have to send a separate request for each file, what can be quite inefficient.

Some references:

Though Microsoft does not recommend FtpWebRequest for a new development anyway.


Alternatively you can use a 3rd party FTP client implementation that supports the modern MLSD command and/or has built-in support for parsing different formats of the LIST command.

For example, WinSCP .NET assembly supports both.

# 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 = "username"
    Password = "password"
}

try
{
    # Connect
    $session = New-Object WinSCP.Session
    $session.Open($sessionOptions)

    # List files
    $remotePath = "/remote/path"
    $directoryInfo = $session.ListDirectory($remotePath)

    # Find old files
    $limit = (Get-Date).AddDays(-15)

    $oldFiles =
        $directoryInfo.Files |
        Where-Object { -Not $_.IsDirectory } | 
        Where-Object { $_.LastWriteTime -lt $limit }

    # Delete them
    foreach ($oldFileInfo in $oldFiles)
    {
        $session.RemoveFile($oldFileInfo.FullName).Check()
    } 

    Write-Host "Done"
}
finally
{
    # Disconnect, clean up
    $session.Dispose()
}

If you can do with a plain batch file, it's actually even easier with WinSCP scripting:

winscp.com /ini=nul /log=delete.log /command ^
    "open ftp://username:password@ftp.example.com/" ^
    "rm /remote/path/*<15D" ^
    "exit"

See file masks with time constraints.

(I'm the author of WinSCP)


Note that WinSCP does not require any installation. So you can just have its binaries copied around with your batch file or PowerShell script.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...