¿Alternativa nativa a wget en Windows PowerShell?


Respuestas:


237

Aquí hay una simple PS 3.0 y una línea única que funciona y no involucra mucho PS barf:

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

Tenga en cuenta que:

  • wget es un alias para Invoke-WebRequest
  • Invoke-WebRequest devuelve un HtmlWebResponseObject , que contiene muchas propiedades útiles de análisis HTML, como Enlaces, Imágenes, Formularios, InputFields, etc., pero en este caso solo estamos usando el Contenido sin formato
  • El contenido del archivo se almacena en la memoria antes de escribir en el disco, lo que hace que este enfoque no sea adecuado para descargar archivos grandes
  • En las instalaciones de Windows Server Core, deberá escribir esto como

    wget http://blog.stackexchange.com/ -UseBasicParsing -OutFile out.html
    
  • Antes del 20 de septiembre de 2014, sugerí

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

    como respuesta Sin embargo, esto no funciona en todos los casos, ya que el >operador (que es un alias para Out-File) convierte la entrada a Unicode.

Si está utilizando Windows 7, deberá instalar la versión 4 o posterior de Windows Management Framework.

Es posible que hacer un $ProgressPreference = "silentlyContinue"antes Invoke-WebRequestmejore significativamente la velocidad de descarga con archivos grandes; Esta variable controla si se procesa la IU de progreso.


3
Esta es ahora la respuesta correcta, y me encontré con wget probando accidentalmente si tenía instalado el wget real. Molesto que no pueda obtener el nombre de archivo fácilmente (debe especificarlo en la redirección de salida), pero esta opción tiene una mejor interfaz de usuario que el wget real (en mi opinión), así que eso es todo.
Matthew Scharley

13
Pero Windows 7 solo viene con PowerShell 2.0 , y el resultado será "El término 'Invoke-WebRequest' no se reconoce como el nombre de un cmdlet, ...".
Peter Mortensen

16
Advertencia justa: este método colocará todo el contenido del archivo en la memoria antes de escribirlo en el archivo. Esta no es una buena solución para descargar archivos grandes.
im_nullable

2
@im_nullable, buena decisión: lo he agregado a la publicación.
Warren Rumak

1
@dezza He actualizado la respuesta con un enfoque diferente. Pruébalo otra vez.
Warren Rumak

181

Si solo necesita recuperar un archivo, puede usar el método DownloadFile del objeto WebClient :

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

Donde $urles una cadena que representa la URL del archivo y $pathrepresenta la ruta local en la que se guardará el archivo.

Tenga en cuenta que $pathdebe incluir el nombre del archivo; no puede ser solo un directorio.


32
Hasta ahora, esta ha sido la mejor solución propuesta. También dado que parece que puedo reescribirlo en un formato de línea, ya (new-object System.Net.WebClient).DownloadFile( '$url, $path)que es la mejor correspondencia wgetque he visto hasta ahora. ¡Gracias!
jsalonen

3
Como nota al margen, también puede hacerlo asincrónicamente usando algo como (new-object System.Net.WebClient) .DownloadFileAsync (url, filePath)
James

¿Podemos buscar un texto en particular a través de Webclient y enviarlo a un bloc de notas? gracias
Mowgli

66
Sí, esto funciona de fábrica en Windows 7 ( que viene con PowerShell 2.0 ). Muestra: $client.DownloadFile( "http://blog.stackexchange.com/", "c:/temp2/_Download.html")
Peter Mortensen

3
Para obtener una URL e ignorar los resultados (p. Ej., Parte de un script de calentamiento de IIS) use DownloadData:(new-object System.Net.WebClient).DownloadData($url) | Out-Null
BurnsBA

85

Existe Invoke-WebRequesten la próxima versión 3 de PowerShell:

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

99
toda la elegancia de dd...
gWaldo

1
@gWaldo estás bromeando: es una alegría usarlo (hablando como alguien que solo está aprendiendo PS)

8
Solo quiero decir que el -Outfileparámetro parece extraño cuando puedes usar >(para sobrescribir) o >>(para agregar) a un archivo.
gWaldo

55
@gWaldo o incluso deducir el nombre de archivo de la URL como lo wgethace :)
Peltier

55
Y a partir de PS 4.0, wgety curlestán alias a Invoke-WebRequest( iwr) por defecto: D
Bob

18

Es un poco desordenado, pero existe esta publicación de blog que le da instrucciones para descargar archivos.

Alternativamente (y este es uno que recomendaría) puede usar BITS:

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

Mostrará el progreso y descargará el archivo al directorio actual.


3
BITS depende del soporte en el extremo del servidor; si está disponible, esto funciona en segundo plano y puede obtener actualizaciones de progreso con otros cmdlets.
Richard

2
Traté de buscar google.com , pero todo lo que obtengo es Start-BitsTransfer : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)). Estoy perplejo: |
jsalonen

1
@jsalonen Creo que BITS solo descargará archivos en lugar de páginas. Como dice Richard, depende de algún soporte del lado del servidor (aunque no creo que sea específico de Microsoft).
Matthew Steeples

Veo y creo que entiendo el uso de BITS, sin embargo, no es lo que estoy buscando aquí.
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

Esto es básicamente la línea única V3 de Warren (increíble) (¡gracias por esto!) , Con solo un pequeño cambio para que funcione en un PowerShell V4.

El one-liner de Warren, que simplemente usa en wgetlugar de iwr, aún debería funcionar para V3 (al menos, supongo; sin embargo, no lo probó). De todas formas. Pero cuando intente ejecutarlo en un V4 PowerShell (como lo intenté), verá que PowerShell no se resuelve wgetcomo un cmdlet / programa válido.

Para aquellos interesados, eso es, como leí en el comentario de Bob en respuesta a la respuesta aceptada (¡gracias, hombre!) , Porque a partir de PowerShell V4, wgety curltienen un alias Invoke-WebRequest, configurado iwrde manera predeterminada . Por lo tanto, wgetno se puede resolver (y tampoco curlpuede funcionar aquí) .


4

Aquí hay una función de PowerShell que resuelve URL cortas antes de descargar el archivo

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

Úselo así para descargar el archivo a la carpeta actual:

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

O para descargar el archivo a una carpeta específica:

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

2

La siguiente función obtendrá una 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)
}

Algunos comentarios:

  1. Las últimas 4 líneas solo son necesarias si está detrás de un proxy de autenticación. Para un uso simple, (New-Object Net.WebClient).DownloadFile($url, $path)funciona bien.
  2. La ruta debe ser absoluta, ya que la descarga no se realiza en su directorio actual, por lo que las rutas relativas harán que la descarga se pierda en algún lugar.
  3. La if (!$path) {...}sección maneja el caso simple en el que solo desea descargar el archivo al directorio actual utilizando el nombre dado en la URL.

1

Use Windows 10 bash shell que incluye wget una vez que la función de Windows está configurada.

Cómo instalar Ubuntu bash shell en Windows:

YouTube: ¡Ejecutar Bash en Ubuntu en Windows!

Subsistema de Windows para la documentación de Linux


1
Considere agregar alguna referencia citada a esta respuesta que respalde lo que dice en caso de que el enlace falle, por lo que el contenido de la respuesta todavía está disponible y actualmente solo está disponible a través de ese enlace según su sugerencia.
Pimp Juice IT

0

Si su Windows es lo suficientemente nuevo (como la versión 1809 o más reciente), hay un rizo "real" disponible. curl tiene la opción de línea de comandos "-O" (letra O mayúscula; ¡la letra minúscula no hará lo mismo!) La opción "-O", alternativamente "--remote-name" le dice a curl que el archivo guardado obtiene mismo nombre que la parte del nombre de archivo de la URL.

Uno necesita comenzar esto como "curl.exe", para distinguirlo del "curl" de Alias ​​para "Invoke-WebRequest". Por cierto, funciona en cmd.exe sin cambios.

Usando el mismo ejemplo que en otra respuesta aquí

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

(El sitio no me permitirá agregar esto como un comentario, ya que aparentemente necesito más "reputación" para eso, por lo que obtiene una nueva respuesta)


0

Invoke-WebRequest con el parámetro -outfile espera una cadena, por lo que si su nombre de archivo comienza con un número y no está entre comillas, no se crea ningún archivo de salida.

p.ej. Invoke-WebRequest -Uri "http://www.google.com/" -outfile "2.pdf"

Esto no afecta a los nombres de archivo que comienzan con una letra.


Esta solución se menciona en otras respuestas ( wgetes un alias de Invoke-WebRequest, y uno similar al anterior)
bertieb

El punto de la respuesta fue enfatizar la nota. Ninguna de las respuestas trata con la creación de ningún archivo debido al error de sintaxis.
Zimba

Eso realmente debería ser un comentario sobre la otra respuesta [s]
bertieb

Esta respuesta no se proporciona en otras respuestas ni es similar a la anterior.
Zimba

-1

Esto debería funcionar para evitar las cosas no inicializadas del navegador. Tenga en cuenta el parámetro "-UseBasicParsing".

Invoke-WebRequest http://localhost -UseBasicParsing

(1) ¿Qué es "el material no inicializado por el navegador"? (2) Tenga en cuenta que la respuesta aceptada ya menciona -UseBasicParsing.
Scott
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.