Alternativa nativa a wget in Windows PowerShell?


Risposte:


237

Ecco un semplice PS 3.0 e successivo one-liner che funziona e non coinvolge molto PS barf:

wget http://blog.stackexchange.com/ -OutFile out.html

Nota che:

  • wget è un alias per Invoke-WebRequest
  • Invoke-WebRequest restituisce un oggetto HtmlWebResponseObject , che contiene molte utili proprietà di analisi HTML come collegamenti, immagini, moduli, campi di input, ecc., Ma in questo caso stiamo solo utilizzando il contenuto non elaborato
  • Il contenuto del file viene archiviato in memoria prima di scrivere su disco, rendendo questo approccio inadatto per il download di file di grandi dimensioni
  • Sulle installazioni di Windows Server Core, dovrai scrivere come

    wget http://blog.stackexchange.com/ -UseBasicParsing -OutFile out.html
    
  • Prima del 20 settembre 2014, ho suggerito

    (wget http://blog.stackexchange.com/).Content >out.html
    

    come risposta. Tuttavia, ciò non funziona in tutti i casi, poiché l' >operatore (che è un alias per Out-File) converte l'input in Unicode.

Se si utilizza Windows 7, sarà necessario installare la versione 4 o successiva di Windows Management Framework.

Potresti scoprire che fare un $ProgressPreference = "silentlyContinue"prima Invoke-WebRequestmigliorerà significativamente la velocità di download con file di grandi dimensioni; questa variabile controlla se viene visualizzata l'interfaccia utente di avanzamento.


3
Questa è ora la risposta corretta, e ho incontrato wget per sbaglio test se avevo installato il wget reale. È fastidioso che non riesca a ottenere facilmente il nome del file (è necessario specificarlo nel reindirizzamento dell'output), ma questa opzione ha un'interfaccia utente migliore rispetto al wget reale (secondo me), quindi c'è quello.
Matthew Scharley,

13
Ma Windows 7 viene fornito solo con PowerShell 2.0 e il risultato sarà "Il termine 'Invoke-WebRequest' non è riconosciuto come il nome di un cmdlet, ...".
Peter Mortensen,

16
Avviso equo: questo metodo metterà in memoria l'intero contenuto del file prima di scriverlo nel file. Questa non è una buona soluzione per il download di file di grandi dimensioni.
im_nullable

2
@im_nullable, buona chiamata - L'ho aggiunto al post.
Warren Rumak,

1
@dezza Ho aggiornato la risposta con un approccio diverso. Provaci ancora.
Warren Rumak,

181

Se hai solo bisogno di recuperare un file, puoi usare il metodo DownloadFile dell'oggetto WebClient :

$client = New-Object System.Net.WebClient
$client.DownloadFile($url, $path)

Dove si $urltrova una stringa che rappresenta l'URL del file e $pathrappresenta il percorso locale in cui verrà salvato il file.

Nota che $pathdeve includere il nome del file; non può essere solo una directory.


32
Finora questa è stata la migliore soluzione proposta. Dato anche che sembra che posso riscriverlo in un formato di riga in (new-object System.Net.WebClient).DownloadFile( '$url, $path)quanto è la migliore corrispondenza per wgetcui ho visto finora. Grazie!
jsalonen,

3
Come nota a margine puoi anche farlo in modo asincrono usando qualcosa come (new-object System.Net.WebClient). DownloadFileAsync (url, filePath)
James

Possiamo recuperare un particolare testo tramite Webclient e ritagliarlo su un blocco note? grazie
Mowgli il

6
Sì, funziona immediatamente su Windows 7 ( fornito con PowerShell 2.0 ). Esempio: $client.DownloadFile( "http://blog.stackexchange.com/", "c:/temp2/_Download.html")
Peter Mortensen,

3
Per ottenere semplicemente un URL e ignorare i risultati (ad esempio, parte di uno script di riscaldamento IIS) utilizzare DownloadData:(new-object System.Net.WebClient).DownloadData($url) | Out-Null
BurnsBA

86

C'è Invoke-WebRequestnella prossima versione di PowerShell 3:

Invoke-WebRequest http://www.google.com/ -OutFile c:\google.html

9
tutta l'eleganza di dd...
gWaldo

1
@gWaldo stai scherzando - questa è una gioia da usare (parlando come qualcuno che sta imparando il PS)
Jack Douglas

8
Intendo solo che il -Outfileparametro sembra estraneo quando potresti semplicemente usare >(per sovrascrivere) o >>(per aggiungere) a un file.
gWaldo,

5
@gWaldo o addirittura deduci il nome file dall'URL proprio come wgetfa :)
Peltier,

5
E a partire da PS 4.0, wgete curlsono aliasted a Invoke-WebRequest( iwr) per impostazione predefinita: D
Bob

18

È un po 'disordinato ma c'è questo post sul blog che ti dà le istruzioni per il download di file.

In alternativa (e questo è uno che consiglierei) puoi usare BITS:

Import-Module BitsTransfer
Start-BitsTransfer -source "http://urlToDownload"

Mostrerà l'avanzamento e scaricherà il file nella directory corrente.


3
BITS si basa sul supporto a livello del server, se disponibile funziona in background e puoi ottenere aggiornamenti sui progressi con altri cmdlet.
Richard,

2
Ho provato a recuperare google.com , ma tutto quello che ottengo è Start-BitsTransfer : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)). Sono perplesso: |
jsalonen,

1
@jsalonen Penso che BITS scaricherà solo file anziché pagine. Come dice Richard, si basa su un supporto lato server (anche se non credo sia specifico per Microsoft).
Matthew Steeples,

Vedo e penso di avere ragione nell'usare BITS, tuttavia, non è quello che sto cercando qui.
jsalonen,

6

PowerShell V4 One-liner:

(iwr http://blog.stackexchange.com/).Content >index.html`

o

(iwr http://demo.mediacore.tv/files/31266.mp4).Content >video.mp4

Questo è fondamentalmente il fantastico (unico) V3 di Warren (grazie per questo!) - con solo una piccola modifica per farlo funzionare in un PowerShell V4.

Il one-liner di Warren - che usa semplicemente wgetpiuttosto che iwr- dovrebbe ancora funzionare per V3 (almeno, immagino; non l'ho provato, però). Comunque. Ma quando provo a eseguirlo in un PowerShell V4 (come ho provato), vedrai che PowerShell non si risolve wgetcome un cmdlet / programma valido.

Per coloro che sono interessati, questo è - come ho raccolto dal commento di Bob in risposta alla risposta accettata (grazie, amico!) - perché a partire da PowerShell V4, wgete curlsono alias Invoke-WebRequest, impostato di iwrdefault . Pertanto, wgetnon può essere risolto (così come curlnon può funzionare qui) .


4

Ecco una funzione di PowerShell che risolve URL brevi prima di scaricare il file

function Get-FileFromUri {  
    param(  
        [parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [string]
        [Alias('Uri')]
        $Url,
        [parameter(Mandatory=$false, Position=1)]
        [string]
        [Alias('Folder')]
        $FolderPath
    )
    process {
        try {
            # resolve short URLs
            $req = [System.Net.HttpWebRequest]::Create($Url)
            $req.Method = "HEAD"
            $response = $req.GetResponse()
            $fUri = $response.ResponseUri
            $filename = [System.IO.Path]::GetFileName($fUri.LocalPath);
            $response.Close()
            # download file
            $destination = (Get-Item -Path ".\" -Verbose).FullName
            if ($FolderPath) { $destination = $FolderPath }
            if ($destination.EndsWith('\')) {
                $destination += $filename
            } else {
                $destination += '\' + $filename
            }
            $webclient = New-Object System.Net.webclient
            $webclient.downloadfile($fUri.AbsoluteUri, $destination)
            write-host -ForegroundColor DarkGreen "downloaded '$($fUri.AbsoluteUri)' to '$($destination)'"
        } catch {
            write-host -ForegroundColor DarkRed $_.Exception.Message
        }  
    }  
}  

Usalo in questo modo per scaricare il file nella cartella corrente:

Get-FileFromUri http://example.com/url/of/example/file  

O per scaricare il file in una cartella specificata:

Get-FileFromUri http://example.com/url/of/example/file  C:\example-folder  

2

La seguente funzione otterrà un URL.

function Get-URLContent ($url, $path) {
  if (!$path) {
      $path = Join-Path $pwd.Path ([URI]$url).Segments[-1]
  }
  $wc = New-Object Net.WebClient
  $wc.UseDefaultCredentials = $true
  $wc.Proxy.Credentials = $wc.Credentials
  $wc.DownloadFile($url, $path)
}

Alcuni commenti:

  1. Le ultime 4 righe sono necessarie solo se si è dietro un proxy di autenticazione. Per un uso semplice, (New-Object Net.WebClient).DownloadFile($url, $path)funziona bene.
  2. Il percorso deve essere assoluto, poiché il download non viene eseguito nella directory corrente, pertanto i percorsi relativi comporteranno la perdita del download da qualche parte.
  3. La if (!$path) {...}sezione gestisce il semplice caso in cui si desidera scaricare il file nella directory corrente utilizzando il nome indicato nell'URL.

1

Usa la shell bash di Windows 10 che include wget dopo aver configurato la funzione Windows.

Come installare Ubuntu bash shell su Windows:

YouTube: eseguire Bash su Ubuntu su Windows!

Documentazione relativa al sottosistema Windows per Linux


1
Prendi in considerazione l'aggiunta di alcuni riferimenti citati a questa risposta a supporto di ciò che dichiari nel caso in cui il link dovesse mai scomparire, quindi il contenuto della risposta è ancora disponibile che è attualmente disponibile solo tramite quel link per il tuo suggerimento.
Pimp Juice IT

0

Se Windows è abbastanza nuovo (come la versione 1809 o successiva), è disponibile un ricciolo "reale". curl ha l'opzione della riga di comando "-O" (lettera maiuscola O; la lettera minuscola non farà lo stesso!) L'opzione "-O", in alternativa "--remote-name" dice a curl, che il file salvato ottiene il stesso nome della parte del nome file dell'URL.

Uno deve iniziare come "curl.exe", per discernerlo dall'alias "curl" per "Invoke-WebRequest". Per inciso funziona in cmd.exe senza modifiche.

Utilizzando lo stesso esempio di un'altra risposta qui

curl.exe -O http://demo.mediacore.tv/files/31266.mp4

(Il sito non mi consentirà di aggiungere questo come commento, poiché a quanto pare ho bisogno di più "reputazione" per questo - quindi ottiene una nuova risposta)


0

Invoke-WebRequest con il parametro -outfile prevede una stringa, quindi se il nome file inizia con un numero e non è racchiuso tra virgolette, non viene creato alcun file di output.

per esempio. Invoke-WebRequest -Uri "http://www.google.com/" -outfile "2.pdf"

Ciò non influisce sui nomi dei file che iniziano con una lettera.


Questa soluzione è menzionata in altre risposte ( wgetè un alias di Invoke-WebRequest, e uno simile al precedente)
bertieb,

Il punto della risposta era enfatizzare la nota. Nessuna delle risposte si occupa di nessun file creato a causa dell'errore di sintassi.
Zimba,

Questo dovrebbe davvero essere un commento sull'altra risposta [s]
bertieb,

Questa risposta non è fornita in altre risposte né simile a quella sopra.
Zimba,

-1

Questo dovrebbe funzionare per te per aggirare le cose senza inizializzazione del browser. Nota il parametro "-UseBasicParsing".

Invoke-WebRequest http://localhost -UseBasicParsing

(1) Che cos'è "l'inizializzazione senza browser"? (2) Nota che la risposta accettata menziona già -UseBasicParsing.
Scott,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.