Shell – Batch Script using Powershell to download from the web

batchdownloadpowershell

Being that most of my work is done remotely, I have a batch script which downloads all my tools from my FTP server to the client's PC. I just copy and paste the text into notepad on the client's PC and save it as a batch and run it.

This works great, but the problem is, the programs I use get updated every so often – so I would be downloading old versions.
By doing a little research, I found that PowerShell can download files directly from the web.

Download a file via HTTP from a script in Windows

How to execute PowerShell commands from a batch file?

It seems that all the pieces are there, but I don't know anything about PowerShell at all and I'm a total amateur with batch. Further, I guess you can't just call up PowerShell in the batch script and start writing in PowerShell.

So here is the end goal;
To write a batch script which uses PowerShell to download files from different websites (I would provide URLs). Instead of downloading the files from my FTP server, the script would download the programs right from the source.

Best Answer

This method uses the PowerShell version 2 onward compatible and uses System.Net.WebClient class.

Creates an array then adds required URL's to the array. Specify your download location, then for each item in your array, generate a filename which the System.Net.WebClient file parameter requires by using the PowerShell -Split Operator for the string from the last occurrence of the forward slash.

$Urls = @()
$Urls += "https://your/first/download/path/.ext"
$Urls += "https://your/next/download/path/.ext"

$OutPath = "C:\Path\to\download\"

ForEach ( $item in $Urls) {
$file = $OutPath +  ($item).split('/')[-1]
(New-Object System.Net.WebClient).DownloadFile($item, $file)
}

Alternatively use the Invoke-WebRequest as per @McDonald's comment or the Invoke-WebRequest alias wget which are both available from PowerShell version 3 onwards but may be slower

$Urls = @()
$Urls += "https://your/first/download/path/.ext"
$Urls += "https://your/next/download/path/.ext"

$OutPath = "C:\Path\to\download\"

ForEach ( $item in $Urls) {
$file = $OutPath +  ($item).split('/')[-1]
Invoke-WebRequest -Uri $item -Outfile $file
}

Save either script as "C:\Path\to\download_script.ps1"

create and run .bat file with the content

PowerShell -File  "C:\Path\to\download_script.ps1"

or run the .ps1 file from PowerShell

EDIT To accommodate your comment into my answer you can change the array into a multi column array and call the item heading as a . attribute

$Urls = @()
$item = "" | Select path,outpath,name
$item.path = "https://your/first/download/path/.ext"
$item.outpath = "C:\Path\to\download\"
$item.name = "Name1.ext"
$Urls = $Urls + $item

$item = "" | Select path,outpath,name
$item.path = "https://your/next/download/path/.ext"
$item.outpath = "C:\Path\to\download\"
$item.name = "Name2.ext"
$Urls = $Urls + $item

ForEach ( $item in $Urls) {
$file = ($item.outpath) + ($item.name)
(New-Object System.Net.WebClient).DownloadFile($item.path, $file)
}
Related Question