Alternative native à wget dans Windows PowerShell?


284

Je sais que je peux télécharger et installer la bibliothèque susmentionnée (wget pour Windows), mais ma question est la suivante:

Dans Windows PowerShell, existe-t-il une alternative native à wget?

J'ai wgetsimplement besoin de récupérer un fichier depuis une URL donnée avec HTTP GET. Par exemple:

wget http://www.google.com/

Réponses:


236

Voici un simple PS 3.0 et plus récent one-liner qui fonctionne et qui implique peu de PS:

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

Notez que:

  • wget est un alias pour Invoke-WebRequest
  • Invoke-WebRequest renvoie un objet HTML WebResponseObject , qui contient de nombreuses propriétés d'analyse HTML utiles, telles que des liens, des images, des formulaires, des champs de saisie, etc., mais dans ce cas, nous utilisons simplement le contenu brut.
  • Le contenu du fichier est stocké en mémoire avant l'écriture sur le disque, rendant cette approche inutilisable pour le téléchargement de fichiers volumineux.
  • Sur les installations Windows Server Core, vous devez écrire ceci sous la forme suivante:

    wget http://blog.stackexchange.com/ -UseBasicParsing -OutFile out.html
    
  • Avant le 20 septembre 2014, j'ai suggéré

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

    comme une réponse. Cependant, cela ne fonctionne pas dans tous les cas, car l' >opérateur (qui est un alias pour Out-File) convertit l'entrée en Unicode.

Si vous utilisez Windows 7, vous devrez installer la version 4 ou plus récente de Windows Management Framework.

Vous constaterez peut-être que le fait d’ $ProgressPreference = "silentlyContinue"avant Invoke-WebRequestaméliorera considérablement la vitesse de téléchargement des gros fichiers; cette variable contrôle si l'interface utilisateur de progression est rendue.


3
C’est maintenant la bonne réponse, et j’ai rencontré wget en testant accidentellement si j’avais le wget réel installé. Ennuyeux qu'il ne puisse pas obtenir facilement le nom de fichier (vous devez le spécifier dans la redirection de sortie), mais cette option a une meilleure interface utilisateur que le vrai wget (à mon avis), donc voilà.
Matthew Scharley

13
Mais Windows 7 n’est fourni qu’avec PowerShell 2.0 et le résultat sera le suivant: "Le terme 'Invoke-WebRequest' n’est pas reconnu comme nom d’une cmdlet, ...".
Peter Mortensen

16
Avertissement juste: Cette méthode mettra tout le contenu du fichier en mémoire avant de l'écrire dans le fichier. Ce n'est pas une bonne solution pour télécharger des fichiers volumineux.
im_nullable

2
@im_nullable, good call - je l'ai ajouté à l'article.
Warren Rumak

1
@dezza J'ai mis à jour la réponse avec une approche différente. Essaye encore.
Warren Rumak

181

Si vous avez juste besoin de récupérer un fichier, vous pouvez utiliser la méthode DownloadFile de l' objet WebClient :

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

$urlest une chaîne représentant l'URL du fichier et $pathle chemin d'accès local dans lequel le fichier sera enregistré.

Notez que $pathdoit inclure le nom du fichier; ce ne peut pas être juste un répertoire.


32
Jusqu'à présent, cela a été la meilleure solution proposée. De plus, étant donné qu'il semble que je peux réécrire le texte sur une ligne, (new-object System.Net.WebClient).DownloadFile( '$url, $path)c'est la meilleure correspondance que wgetj'ai vue jusqu'à présent. Merci!
Jsalonen

3
En remarque, vous pouvez également le faire de manière asynchrone en utilisant quelque chose comme (new-object System.Net.WebClient) .DownloadFileAsync (url, filePath)
James

Pouvons-nous récupérer un texte particulier via Webclient et le transférer vers un bloc-notes? merci
Mowgli

6
Oui, cela fonctionne immédiatement sous Windows 7 ( fourni avec PowerShell 2.0 ). Exemple: $client.DownloadFile( "http://blog.stackexchange.com/", "c:/temp2/_Download.html")
Peter Mortensen

3
Pour simplement obtenir une URL et ignorer les résultats (par exemple, une partie d'un script de préchauffage IIS), utilisez DownloadData:(new-object System.Net.WebClient).DownloadData($url) | Out-Null
BurnsBA

85

Il y a Invoke-WebRequestdans la prochaine version de PowerShell 3:

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

9
toute l'élégance de dd...
gWaldo

1
@gWaldo vous plaisantez - c'est une joie à utiliser (en tant que quelqu'un qui apprend à apprendre le PS)

8
Je veux juste dire que le -Outfileparamètre semble étranger lorsque vous pouvez simplement utiliser >(écraser) ou >>(ajouter) à un fichier.
gWaldo

5
@gWaldo ou même déduire le nom de fichier de l'URL, tout comme wget:)
Peltier

5
Et à partir de PS 4.0, wgetet curlsont aliasted à Invoke-WebRequest( iwr) par défaut: D
Bob

18

C'est un peu brouillon, mais il y a cet article de blog qui vous donne des instructions pour télécharger des fichiers.

Alternativement (et c'est celui que je recommanderais), vous pouvez utiliser BITS:

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

Il montrera la progression et téléchargera le fichier dans le répertoire actuel.


3
BITS repose sur la prise en charge côté serveur, si disponible, cela fonctionne en arrière-plan et vous pouvez obtenir des mises à jour de progression avec d'autres applets de commande.
Richard

2
J'ai essayé d'aller chercher google.com , mais tout ce que je reçois, c'est Start-BitsTransfer : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)). Je suis perplexe: |
Jsalonen

1
@ jsalonen Je pense que BITS ne téléchargera que des fichiers plutôt que des pages. Comme Richard le dit, cela dépend du support côté serveur (bien que je ne pense pas que ce soit spécifique à Microsoft).
Matthew Steeples

Je vois et je pense que je comprends le point en utilisant BITS, cependant, ce n'est pas ce que je cherche ici.
Jsalonen

6

PowerShell V4 One-Liner:

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

ou

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

Il s’agit essentiellement de V3 one-liner de Warren (génial) (merci pour cela!) - avec juste un changement minime afin de le faire fonctionner dans un V4 PowerShell.

Le one-liner de Warren - qui utilise simplement wgetplutôt que de iwr- devrait toujours fonctionner pour V3 (du moins, je suppose; je ne l’ai pas testé, cependant). En tous cas. Mais lorsque vous tentez de l'exécuter dans un PowerShell V4 (comme je l'ai essayé), vous verrez que PowerShell ne parvient pas à résoudre en wgettant qu'applet de commande / programme valide.

Pour les intéressés, c'est - comme je l' ai pris de commentaire de Bob en réponse à la réponse acceptée (merci, mec!) - parce que de PowerShell V4, wgetet curlsont Données associées Invoke-WebRequest, mis à iwrpar défaut . Ainsi, wgetne peut pas être résolu (ainsi que curlne peut pas fonctionner ici) .


4

Voici une fonction PowerShell qui résout les URL courtes avant de télécharger le fichier.

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

Utilisez-le comme ceci pour télécharger le fichier dans le dossier actuel:

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

Ou pour télécharger le fichier dans un dossier spécifié:

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

2

La fonction suivante obtiendra une 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)
}

Certains commentaires:

  1. Les 4 dernières lignes ne sont nécessaires que si vous êtes derrière un proxy d’authentification. Pour une utilisation simple, (New-Object Net.WebClient).DownloadFile($url, $path)fonctionne bien.
  2. Le chemin doit être absolu, car le téléchargement n’est pas effectué dans votre répertoire actuel. Par conséquent, les chemins relatifs entraîneront une perte du téléchargement quelque part.
  3. La if (!$path) {...}section traite le cas simple où vous souhaitez simplement télécharger le fichier dans le répertoire en cours en utilisant le nom indiqué dans l'URL.

1

Utilisez Windows 10 shell bash qui inclut wget une fois la fonctionnalité Windows configurée.

Comment installer le shell Ubuntu bash sous Windows:

YouTube: Lancer Bash sur Ubuntu sous Windows!

Documentation du sous-système Windows pour Linux


1
Pensez à ajouter quelques références citées à cette réponse à l’appui de ce que vous déclarez au cas où le lien mourrait afin que le contenu de la réponse soit toujours disponible et qu’il ne soit actuellement disponible que par ce lien, selon votre suggestion.
Pimp Juice IT

0

Si votre Windows est suffisamment nouveau (comme la version 1809 ou plus récente), il existe une "vraie" boucle disponible. curl a l'option de ligne de commande "-O" (lettre majuscule O; une lettre minuscule ne fera pas de même!) même nom que la partie nom de fichier de l'URL.

Il faut commencer par "curl.exe" pour le distinguer de l'alias "curl" de "Invoke-WebRequest". Incidemment, cela fonctionne dans cmd.exe sans modifications.

En utilisant le même exemple que dans une autre réponse ici

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

(Le site ne me permet pas d'ajouter ceci en tant que commentaire, car j'ai apparemment besoin de plus de "réputation" pour cela - donc cela donne une nouvelle réponse)


0

Invoke-WebRequest avec le paramètre -outfile attend une chaîne. Ainsi, si votre nom de fichier commence par un nombre et n'est pas placé entre guillemets, aucun fichier de sortie n'est créé.

par exemple. Invoke-WebRequest -Uri "http://www.google.com/" -outfile "2.pdf"

Cela n'affecte pas les noms de fichiers commençant par une lettre.


Cette solution est mentionnée dans d'autres réponses ( wgetest un alias de Invoke-WebRequestet un nom similaire à celui ci-dessus)
bertieb

Le but de la réponse était de souligner la note. Aucune des réponses ne traite du fait qu'aucun fichier n'a été créé en raison d'une erreur de syntaxe.
Zimba

Cela devrait vraiment être un commentaire sur l'autre réponse [s]
bertieb

Cette réponse n'est pas fournie dans d'autres réponses, ni similaire à celle ci-dessus.
Zimba

-1

Cela devrait fonctionner pour vous permettre de contourner les éléments non initialisés par le navigateur. Notez le paramètre "-UseBasicParsing".

Invoke-WebRequest http://localhost -UseBasicParsing

(1) Qu'est-ce que «la partie sans navigateur initialisée»? (2) Notez que la réponse acceptée mentionne déjà -UseBasicParsing.
Scott
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.