Windows 上的命令行从 FTP 站点获取最新文件
Command line on Windows to get latest files from FTP site
我需要 Windows 上命令行的批处理脚本 运行,它会从 FTP 站点下载最新文件(有时最新文件可能不止一个文件)。
我使用了 WinSCP.com
中的以下命令,但我只得到一个最新文件。可以给我一些指导吗?
get -latest *.txt
Wxample:使用上面的命令我只得到文件名 XYZ.txt
文件,我希望有一个脚本能够同时获得 ABC.txt
和 ZZZ.txt
.
filename last written date
------------ ----------------------
ABC.txt 2016-01-01
ZZZ.txt 2016-01-01
A123.txt 2015-12-10
没有基于日期下载多个文件的内置命令,我们必须手动完成。
标准 ls
输出是人类可读的,但不能按日期排序:
D--------- 0 0 Aug 21 15:32:37 2016 Default
我们需要使用 /xmllog=
参数的 xml 日志:
<?xml version="1.0" encoding="UTF-8"?>
<session xmlns="........." name="USER@localhost" start="2016-08-23T15:41:10.708Z">
<ls>
<destination value="/temp" />
<files>
<file>
<filename value=".." />
<type value="D" />
<modification value="1899-12-30T02:00:00.000Z" />
<permissions value="---------" />
</file>
很好,每个文件都有一个机器可读的日期、名称、类型(D 代表目录,我们将跳过它们)。
批处理文件。
(注释分隔符也是代码的一部分)
@echo off
: Setup
setlocal enableDelayedExpansion
set "WinSCP=C:\somepath\WinSCP.com"
set "ftp=ftp://USER:PASSWORD@ftp.server.com"
set "remoteFolder=/someFolderNoTrailingSlash"
: List all ftp files
"%WinSCP%" ^
/command "open %ftp%" "ls ""%remoteFolder%""" "exit" ^
/xmllog="%temp%\ftplog.xml" >nul
(
set isDirectory=
for /f "tokens=1,3 delims=<= " %%a in ('type "%temp%\ftplog.xml"') do (
if "%%a"=="filename" (set "line=%%~b" & set isDirectory=)
if "%%a"=="type" if "%%~b"=="D" (set isDirectory=yes)
if "%%a"=="modification" if not defined isDirectory (
set "line=%%~b*!line!"
echo !line!
)
)
) > "%temp%\ftplist.txt"
: Sort by date and make a WinSCP script to get the latest files with same date
set lastDate=
(
echo open %ftp%
for /f "delims=* tokens=1,2" %%a in ('
sort /reverse "%temp%\ftplist.txt"
') do (
for /f "delims=T" %%c in ("%%a") do set thisDate=%%c
if defined lastDate (
if not !thisDate!==!lastDate! goto download
) else (
set lastDate=!thisDate!
)
echo get -preservetime "%remoteFolder%/%%b"
)
) > "%temp%\ftpscript.txt"
if not defined lastDate goto cleanup
: Download and cleanup temporary files
:download
"%WinSCP%" /script="%temp%\ftpscript.txt" /command "exit"
:cleanup
del "%temp%\ftplog.xml" "%temp%\ftplist.txt" "%temp%\ftpscript.txt"
pause
虽然这可以通过普通的 WinSCP 脚本和批处理文件来实现,因为 shows, the code would be much more readable in a more advanced language like PowerShell with a use of the WinSCP .NET assembly。
下面的代码部分基于示例 Downloading the most recent file。
param (
$session = "ftp://USER:PASSWORD@ftp.server.com",
$remotePath = "/remote/path",
$localPath = "C:\local\path"
)
try
{
Add-Type -Path "WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.ParseUrl($session)
try
{
Write-Host "Connecting..."
$session = New-Object WinSCP.Session
$session.Open($sessionOptions)
$files = $session.ListDirectory($remotePath).Files
$latest_file =
$files |
Where-Object { -Not $_.IsDirectory } |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
Write-Host (
"Latest file is $latest_file created on $($latest_file.LastWriteTime)")
$day = Get-Date -date $latest_file.LastWriteTime -hour 0 -minute 0 -second 0
$latest_files =
$files |
Where-Object { -Not $_.IsDirectory } |
Where-Object { $_.LastWriteTime -ge $day }
Write-Host "Downloading $($latest_files.Count) files created after $day"
foreach ($file in $latest_files)
{
$path = $file.FullName
Write-Host $path
$session.GetFiles(
[WinSCP.RemotePath]::EscapeFileMask($path),
(Join-Path $localPath $file.Name)).Check()
}
Write-Host "Done"
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
exit 0
}
catch [Exception]
{
Write-Host $_.Exception.Message
exit 1
}
我需要 Windows 上命令行的批处理脚本 运行,它会从 FTP 站点下载最新文件(有时最新文件可能不止一个文件)。
我使用了 WinSCP.com
中的以下命令,但我只得到一个最新文件。可以给我一些指导吗?
get -latest *.txt
Wxample:使用上面的命令我只得到文件名 XYZ.txt
文件,我希望有一个脚本能够同时获得 ABC.txt
和 ZZZ.txt
.
filename last written date
------------ ----------------------
ABC.txt 2016-01-01
ZZZ.txt 2016-01-01
A123.txt 2015-12-10
没有基于日期下载多个文件的内置命令,我们必须手动完成。
标准 ls
输出是人类可读的,但不能按日期排序:
D--------- 0 0 Aug 21 15:32:37 2016 Default
我们需要使用 /xmllog=
参数的 xml 日志:
<?xml version="1.0" encoding="UTF-8"?>
<session xmlns="........." name="USER@localhost" start="2016-08-23T15:41:10.708Z">
<ls>
<destination value="/temp" />
<files>
<file>
<filename value=".." />
<type value="D" />
<modification value="1899-12-30T02:00:00.000Z" />
<permissions value="---------" />
</file>
很好,每个文件都有一个机器可读的日期、名称、类型(D 代表目录,我们将跳过它们)。
批处理文件。
(注释分隔符也是代码的一部分)
@echo off
: Setup
setlocal enableDelayedExpansion
set "WinSCP=C:\somepath\WinSCP.com"
set "ftp=ftp://USER:PASSWORD@ftp.server.com"
set "remoteFolder=/someFolderNoTrailingSlash"
: List all ftp files
"%WinSCP%" ^
/command "open %ftp%" "ls ""%remoteFolder%""" "exit" ^
/xmllog="%temp%\ftplog.xml" >nul
(
set isDirectory=
for /f "tokens=1,3 delims=<= " %%a in ('type "%temp%\ftplog.xml"') do (
if "%%a"=="filename" (set "line=%%~b" & set isDirectory=)
if "%%a"=="type" if "%%~b"=="D" (set isDirectory=yes)
if "%%a"=="modification" if not defined isDirectory (
set "line=%%~b*!line!"
echo !line!
)
)
) > "%temp%\ftplist.txt"
: Sort by date and make a WinSCP script to get the latest files with same date
set lastDate=
(
echo open %ftp%
for /f "delims=* tokens=1,2" %%a in ('
sort /reverse "%temp%\ftplist.txt"
') do (
for /f "delims=T" %%c in ("%%a") do set thisDate=%%c
if defined lastDate (
if not !thisDate!==!lastDate! goto download
) else (
set lastDate=!thisDate!
)
echo get -preservetime "%remoteFolder%/%%b"
)
) > "%temp%\ftpscript.txt"
if not defined lastDate goto cleanup
: Download and cleanup temporary files
:download
"%WinSCP%" /script="%temp%\ftpscript.txt" /command "exit"
:cleanup
del "%temp%\ftplog.xml" "%temp%\ftplist.txt" "%temp%\ftpscript.txt"
pause
虽然这可以通过普通的 WinSCP 脚本和批处理文件来实现,因为
下面的代码部分基于示例 Downloading the most recent file。
param (
$session = "ftp://USER:PASSWORD@ftp.server.com",
$remotePath = "/remote/path",
$localPath = "C:\local\path"
)
try
{
Add-Type -Path "WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.ParseUrl($session)
try
{
Write-Host "Connecting..."
$session = New-Object WinSCP.Session
$session.Open($sessionOptions)
$files = $session.ListDirectory($remotePath).Files
$latest_file =
$files |
Where-Object { -Not $_.IsDirectory } |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
Write-Host (
"Latest file is $latest_file created on $($latest_file.LastWriteTime)")
$day = Get-Date -date $latest_file.LastWriteTime -hour 0 -minute 0 -second 0
$latest_files =
$files |
Where-Object { -Not $_.IsDirectory } |
Where-Object { $_.LastWriteTime -ge $day }
Write-Host "Downloading $($latest_files.Count) files created after $day"
foreach ($file in $latest_files)
{
$path = $file.FullName
Write-Host $path
$session.GetFiles(
[WinSCP.RemotePath]::EscapeFileMask($path),
(Join-Path $localPath $file.Name)).Check()
}
Write-Host "Done"
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
exit 0
}
catch [Exception]
{
Write-Host $_.Exception.Message
exit 1
}