How to automatically download a specific file type from within a wildcard folder on an FTP server

我怕爱的太早我们不能终老 提交于 2021-02-08 08:34:25

问题


I'm trying to set up a way to automatically download all .mkv files on an ftp server within a folder of which I won't know the whole name. The most I will know is The.Walking.Dead.* Where star represents what I don't know of the folder name. Currently I'm using WinSCP and the closest code I've gotten from here is

@echo off

"C:\Program Files (x86)\WinSCP\WinSCP.com" ^
  /log="D:\Documents\WinSCP Log\WinSCP.log" /ini=nul ^
  /command ^
    "open "ftp://ivay.myseedbox.site/downloads/manual/" ^
    get "/The.Walking.Dead.*/*.mkv" "E:\Torrents\TV Shows\The Walking Dead\Season 8\" ^
    PAUSE
    exit

set WINSCP_RESULT=%ERRORLEVEL%
if %WINSCP_RESULT% equ 0 (
  echo Success
) else (
  echo Error
)

exit /b %WINSCP_RESULT%

But this returns with an error of

< 2017-11-06 12:47:02.172 Script: No file matching 'The.Walking.Dead.*' found.
. 2017-11-06 12:47:02.172 Listing file "E:\Torrents\TV".
. 2017-11-06 12:47:02.172 Retrieving file information...
> 2017-11-06 12:47:02.172 PWD
< 2017-11-06 12:47:02.308 257 "/"
> 2017-11-06 12:47:02.308 CWD /downloads/manual/E:\Torrents\TV
< 2017-11-06 12:47:02.433 550 Failed to change directory.
> 2017-11-06 12:47:02.433 TYPE I
< 2017-11-06 12:47:02.557 200 Switching to Binary mode.
> 2017-11-06 12:47:02.557 SIZE /downloads/manual/E:\Torrents\TV
< 2017-11-06 12:47:02.681 550 Could not get file size.
. 2017-11-06 12:47:02.681 Could not retrieve file information
< 2017-11-06 12:47:02.681 Script: Can't get attributes of file 'E:\Torrents\TV'.
< 2017-11-06 12:47:02.681 Could not retrieve file information

< 2017-11-06 12:47:02.681 Could not get file size.
. 2017-11-06 12:47:02.681 Script: Failed

So what I can see is it's trying to take my folder directory and use it as a file path and also ignoring the space in my local directory and squishing the remote and local directories together. So any help would be appreciated as I have almost no idea what's going on here.


回答1:


When selecting files to transfer, file mask can be used for the last component of the path only.


One thing you can do is:

get -filemask=*.mkv /The.Walking.Dead.* "E:\Torrents\TV Shows\The Walking Dead\Season 8\"

But this will re-create the matching folder (The.Walking.Dead.*) as a subfolder of the target local folder (Season 8).


If you want to download the files (*.mkv) directly to the target local folder (Season 8), you can make WinSCP "rename" the source folder to Season 8:

get -filemask=*.mkv /The.Walking.Dead.* "E:\Torrents\TV Shows\The Walking Dead\Season 8"

Note the absence of the trailing backslash in the target path. It makes WinSCP download the matching source folder (The.Walking.Dead.*) to the target local folder (The Walking Dead, not Season 8!) under a name Season 8. As Season 8 already exists, it won't do anything with it and will directly continue with downloading the contained files.


The previous works for your specific case. In more complex cases, you would need to find out the name of the folder before the download. While it is not impossible to implement this using a plain batch file, it would be very complicated.

In such case, I would suggest using PowerShell with use of WinSCP .NET assembly.

With it, the script (e.g. download.ps1) would be like:

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

Write-Host "Connecting..."
$session = New-Object WinSCP.Session
$session.SessionLogPath = "session.log"
$session.Open($sessionOptions)

$remotePath = "/"
$localPath = "C:\local\path"
$pattern = "The.Walking.Dead.*"
$twdFolder =
    $session.ListDirectory($remotePath).Files |
    Where-Object { $_.IsDirectory -and ($_.Name -like $pattern) } |
    Select-Object -First 1

if ($twdFolder -eq $Null)
{
    Write-Host "No folder matching '$pattern' found."
}
else
{
    Write-Host "Found folder '$($twdFolder.Name)', downloading..."
    $sourcePath = [WinSCP.RemotePath]::Combine($remotePath, $twdFolder.Name)
    $sourcePath = [WinSCP.RemotePath]::Combine($sourcePath, "*")
    $destPath = Join-Path $localPath "*"
    $transferResult = $session.GetFiles($sourcePath, $destPath).Check()
}

Write-Host "Done"

Extract WinSCP automation package along with the script and run the script like:

powershell.exe -ExecutionPolicy Unrestricted -File download.ps1



回答2:


I completely forgot I posted on here and ended up figuring out how to do it myself. So sorry for not replying to anyone. I really appreciate the time you took to help me I just completely forgot about it. May not be the most clean method but it works for me lol. I kinda would like to add a download progress bar but I feel like that would be really complicated. This is what I ended up using:

param (
    $localPath = "E:\Torrents\TV Shows\The Walking Dead\Season 8\",
    $remotePath = "/downloads/manual/The.Walking.Dead.*",
    $fileName = "*"
)

    # Deletes new episode folder just in case one exists 
    Remove-Item "E:\Torrents\TV Shows\The Walking Dead\Season 8\New Episode" -recurse -EA SilentlyContinue

    #Tells the user that the files are being downloaded
    cls
    "Downloading The Walking Dead. This can take a while."
    "Please do not close this window."

try
{
# Load WinSCP .NET assembly
Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"

# Set up session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
    Protocol = [WinSCP.Protocol]::Ftp
    HostName = "removed"
    PortNumber = 21
    UserName = "removed"
    Password = "removed"
}

$session = New-Object WinSCP.Session

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

    # Download the file and throw on any error and deletes the files from  the server
    $session.GetFiles(
        ($remotePath + $fileName),
        ($localPath + $fileName))
    $session.RemoveFiles("/downloads/manual/The.Walking.Dead.*")
}

finally
{
    $session.Dispose()
}

    # Renames the downloaded folder
    Rename-Item "E:\Torrents\TV Shows\The Walking Dead\Season 8\The.Walking.Dead.*" "New Episode" -EA SilentlyContinue

    # Deletes unnecesary files
    Remove-Item "E:\Torrents\TV Shows\The Walking Dead\Season 8\New Episode\*" -exclude *.mkv -EA SilentlyContinue

    # Moves video file to proper directory
    Move-Item "E:\Torrents\TV Shows\The Walking Dead\Season 8\New Episode\*.mkv" "E:\Torrents\TV Shows\The Walking Dead\Season 8" -EA SilentlyContinue

    # Deletes new episode folder to clean things up
    Remove-Item "E:\Torrents\TV Shows\The Walking Dead\Season 8\New Episode" -recurse -EA SilentlyContinue

    exit 0
}
catch [Exception]
{
    Write-Host "Error: $($_.Exception.Message)"
    exit 1
}


来源:https://stackoverflow.com/questions/47143810/how-to-automatically-download-a-specific-file-type-from-within-a-wildcard-folder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!