Alternativa nativa ao wget no Windows PowerShell?


284

Sei que posso baixar e instalar a biblioteca mencionada (wget para Windows), mas minha pergunta é a seguinte:

No Windows PowerShell, existe uma alternativa nativa para wget?

Eu preciso wgetsimplesmente recuperar um arquivo de uma determinada URL com HTTP GET. Por exemplo:

wget http://www.google.com/

Respostas:


237

Aqui está um simples single-liner do PS 3.0 e posterior que funciona e não envolve muito barf PS:

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

Observe que:

  • wget é um apelido para Invoke-WebRequest
  • Invoke-WebRequest retorna um HtmlWebResponseObject , que contém muitas propriedades úteis de análise de HTML, como Links, Imagens, Formulários, InputFields, etc., mas, neste caso, estamos apenas usando o Conteúdo bruto
  • O conteúdo do arquivo é armazenado na memória antes de gravar no disco, tornando essa abordagem inadequada para o download de arquivos grandes.
  • Nas instalações do Windows Server Core, você precisará escrever isso como

    wget http://blog.stackexchange.com/ -UseBasicParsing -OutFile out.html
    
  • Antes de 20 de setembro de 2014, sugeri

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

    como resposta. No entanto, isso não funciona em todos os casos, pois o >operador (que é um alias para Out-File) converte a entrada em Unicode.

Se você estiver usando o Windows 7, precisará instalar a versão 4 ou mais recente do Windows Management Framework.

Você pode achar que fazer isso $ProgressPreference = "silentlyContinue"antes Invoke-WebRequestmelhorará significativamente a velocidade de download com arquivos grandes; essa variável controla se a interface do usuário de progresso é renderizada.


3
Esta é agora a resposta correta, e eu testei acidentalmente o wget se eu tinha o wget real instalado. É irritante que ele não consiga obter o nome do arquivo com facilidade (você deve especificá-lo no redirecionamento de saída), mas essa opção tem uma interface de usuário melhor do que o wget real (na minha opinião), então é isso.
Matthew Scharley

13
Mas o Windows 7 vem apenas com o PowerShell 2.0 , e o resultado será "O termo 'Invoke-WebRequest' não é reconhecido como o nome de um cmdlet, ...".
22416 Peter Mortensen

16
Aviso razoável: esse método colocará todo o conteúdo do arquivo na memória antes de gravá-lo no arquivo. Esta não é uma boa solução para baixar arquivos grandes.
im_nullable

2
@im_nullable, boa chamada - eu adicionei isso à postagem.
Warren Rumak

1
@dezza Atualizei a resposta com uma abordagem diferente. Tente de novo.
Warren Rumak

181

Se você apenas precisar recuperar um arquivo, poderá usar o método DownloadFile do objeto WebClient :

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

Onde $urlé uma string que representa a URL do arquivo e $pathrepresenta o caminho local em que o arquivo será salvo.

Observe que $pathdeve incluir o nome do arquivo; não pode ser apenas um diretório.


32
Até agora, essa foi a melhor solução proposta. Também porque parece que posso reescrevê-lo em um formato de linha, (new-object System.Net.WebClient).DownloadFile( '$url, $path)pois é a melhor correspondência wgetque vi até agora. Obrigado!
jsalonen

3
Como uma nota lateral, você também pode fazer isso de forma assíncrona usando algo como (new-object System.Net.WebClient) .DownloadFileAsync (url, filePath)
James

Podemos buscar um texto específico via Webclient e sair para um bloco de notas? graças
Mowgli

6
Sim, isso funciona imediatamente no Windows 7 ( que acompanha o PowerShell 2.0 ). Exemplo: $client.DownloadFile( "http://blog.stackexchange.com/", "c:/temp2/_Download.html")
Peter Mortensen

3
Para obter apenas uma URL e ignorar os resultados (por exemplo, parte de um script de aquecimento do IIS), use DownloadData:(new-object System.Net.WebClient).DownloadData($url) | Out-Null
BurnsBA

86

Existe Invoke-WebRequestna próxima versão 3 do PowerShell:

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

9
toda a elegância de dd...
gWaldo 31/08/2012

1
@gWaldo você está brincando-esta é uma alegria para usar (falando como alguém PS apenas aprender)
Jack Douglas

8
Só quero dizer que o -Outfileparâmetro parece estranho quando você pode apenas usar >(para substituir) ou >>(para acrescentar) a um arquivo.
gWaldo

5
@gWaldo ou mesmo deduzir o nome do arquivo a partir da URL apenas como wgetse :)
Peltier

5
E a partir do PS 4.0 wgete curlestá alternadamente com Invoke-WebRequest( iwr) por padrão: D
Bob

18

É um pouco confuso, mas há uma postagem no blog que fornece instruções para o download de arquivos.

Como alternativa (e eu recomendo), você pode usar o BITS:

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

Ele mostrará o progresso e fará o download do arquivo no diretório atual.


3
O BITS conta com suporte no final do servidor, se disponível, isso funciona em segundo plano e você pode obter atualizações de progresso com outros cmdlets.
Richard

2
Tentei buscar o google.com , mas tudo o que recebo é Start-BitsTransfer : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)). Estou intrigado: |
precisa saber é o seguinte

1
@jsalonen Eu acho que o BITS baixará apenas arquivos, e não páginas. Como Richard diz, conta com algum suporte do lado do servidor (embora eu não ache que seja específico da Microsoft).
Matthew Steeples

Eu vejo e acho que entendi o uso do BITS, no entanto, não é o que estou procurando aqui.
jsalonen

6

Uma linha do PowerShell V4:

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

ou

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

Essa é basicamente a única linha V3 de Warren (impressionante) (obrigado por isso!) - com apenas uma pequena alteração para fazê-la funcionar em um V4 PowerShell.

O one-liner de Warren - que simplesmente usa wgete não iwr- ainda deve funcionar para a V3 (pelo menos, eu acho; no entanto, não a testei). De qualquer forma. Mas ao tentar executá-lo em um V4 PowerShell (como tentei), você verá o PowerShell falhando ao resolver wgetcomo um cmdlet / programa válido.

Para os interessados, isso é - como eu peguei no comentário de Bob em resposta à resposta aceita (obrigado, cara!) - por causa do PowerShell V4, wgete com o curlalias Invoke-WebRequest, definido como iwrpadrão . Assim, wgetnão pode ser resolvido (assim como curlnão pode funcionar aqui) .


4

Aqui está uma função do PowerShell que resolve URLs curtos antes de baixar o arquivo

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
        }  
    }  
}  

Use-o assim para baixar o arquivo para a pasta atual:

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

Ou, para baixar o arquivo para uma pasta especificada:

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

2

A função a seguir receberá um 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)
}

Alguns comentários:

  1. As últimas 4 linhas são necessárias apenas se você estiver atrás de um proxy de autenticação. Para uso simples, (New-Object Net.WebClient).DownloadFile($url, $path)funciona bem.
  2. O caminho deve ser absoluto, pois o download não é feito no diretório atual, portanto, os caminhos relativos resultarão na perda do download em algum lugar.
  3. A if (!$path) {...}seção trata do caso simples em que você deseja fazer o download do arquivo no diretório atual usando o nome fornecido no URL.

1

Use o shell do Windows 10 bash, que inclui o wget assim que o recurso do Windows estiver configurado.

Como instalar o Ubuntu bash shell no Windows:

YouTube: Executando o Bash no Ubuntu no Windows!

Documentação do subsistema Windows para Linux


1
Considere adicionar algumas referências citadas a esta resposta, dando suporte ao que você declara, caso o link morra, para que o conteúdo da resposta ainda esteja disponível e que esteja disponível atualmente apenas por esse link, de acordo com sua sugestão.
Pimp Juice IT

0

Se o seu Windows for novo o suficiente (como a versão 1809 ou mais recente), há uma curvatura "real" disponível. curl tem a opção de linha de comando "-O" (letra maiúscula O; letras minúsculas não fazem o mesmo!) A opção "-O", ou "-remote-name" informa ao curl, que o arquivo salvo obtém o mesmo nome que a parte do nome do arquivo da URL.

É necessário iniciar isso como "curl.exe", para discerni-lo a partir do alias "curl" para "Invoke-WebRequest". Aliás, ele funciona no cmd.exe sem alterações.

Usando o mesmo exemplo que em outra resposta aqui

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

(O site não permitirá que eu adicione isso como um comentário, já que aparentemente eu preciso de mais "reputação" para isso - então obtém uma nova resposta)


0

O parâmetro Invoke-WebRequest com -outfile espera uma sequência, portanto, se o nome do arquivo começar com um número e não estiver entre aspas, nenhum arquivo de saída será criado.

por exemplo. Invoke-WebRequest -Uri "http://www.google.com/" -outfile "2.pdf"

Isso não afeta os nomes de arquivos iniciados por uma letra.


Esta solução é mencionado em outras respostas ( wgeté uma abreviatura de Invoke-WebRequest, e um semelhante ao acima)
bertieb

O objetivo da resposta foi enfatizar a nota. Nenhuma das respostas trata de nenhum arquivo sendo criado devido ao erro de sintaxe.
Zimba

Isso deve realmente ser um comentário sobre a outra resposta [s]
bertieb

Esta resposta não é fornecida em outras respostas nem similar à acima.
Zimba 23/03

-1

Isso deve funcionar para você contornar o material não inicializado pelo navegador. Observe o parâmetro "-UseBasicParsing".

Invoke-WebRequest http://localhost -UseBasicParsing

(1) O que é "o material não inicializado pelo navegador"? (2) Observe que a resposta aceita já menciona -UseBasicParsing.
Scott
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.