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.