Natywna alternatywa dla wget w Windows PowerShell?


283

Wiem, że mogę pobrać i zainstalować wspomnianą bibliotekę (wget dla Windows), ale moje pytanie brzmi:

Czy w Windows PowerShell istnieje natywna alternatywa dla wget?

Muszę wgetpo prostu pobrać plik z podanego adresu URL za pomocą HTTP GET. Na przykład:

wget http://www.google.com/

Odpowiedzi:


236

Oto prosty PS 3.0, a później jednoliniowy, który działa i nie wymaga dużo PS barf:

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

Uwaga:

  • wget jest pseudonimem dla Invoke-WebRequest
  • Invoke-WebRequest zwraca HtmlWebResponseObject , który zawiera wiele przydatnych właściwości parsowania HTML, takich jak łącza, obrazy, formularze, InputFields itp., Ale w tym przypadku używamy tylko surowej treści
  • Zawartość pliku jest zapisywana w pamięci przed zapisaniem na dysk, co czyni to podejście nieodpowiednim do pobierania dużych plików
  • W instalacjach systemu Windows Server Core musisz zapisać to jako

    wget http://blog.stackexchange.com/ -UseBasicParsing -OutFile out.html
    
  • Zasugerowałem przed 20 września 2014 r

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

    jako odpowiedź. Nie działa to jednak we wszystkich przypadkach, ponieważ >operator (który jest aliasem Out-File) konwertuje dane wejściowe na Unicode.

Jeśli używasz systemu Windows 7, musisz zainstalować wersję 4 lub nowszą z Windows Management Framework.

Może się okazać, że wykonanie tego $ProgressPreference = "silentlyContinue"wcześniej Invoke-WebRequestznacznie poprawi szybkość pobierania dużych plików; ta zmienna kontroluje, czy interfejs postępu jest renderowany.


3
To jest teraz poprawna odpowiedź i przypadkowo wpadłem na wget testowanie, czy mam zainstalowany rzeczywisty wget. Denerwujące, że nie może łatwo pobrać nazwy pliku (musisz ją podać w przekierowaniu wyjścia), ale ta opcja ma lepszy interfejs użytkownika niż prawdziwy wget (moim zdaniem), więc jest.
Matthew Scharley

13
Ale system Windows 7 jest dostarczany tylko z programem PowerShell 2.0 , a wynikiem będzie „Termin„ Invoke-WebRequest ”nie jest rozpoznawany jako nazwa polecenia cmdlet ...”.
Peter Mortensen

16
Uczciwe ostrzeżenie: Ta metoda umieści całą zawartość pliku w pamięci przed zapisaniem go do pliku. To nie jest dobre rozwiązanie do pobierania dużych plików.
im_nullable

2
@im_nullable, dobra rozmowa - dodałem to do wpisu.
Warren Rumak

1
@dezza Zaktualizowałem odpowiedź innym podejściem. Spróbuj ponownie.
Warren Rumak

181

Jeśli potrzebujesz tylko pobrać plik, możesz użyć metody DownloadFile obiektu WebClient :

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

Gdzie $urljest ciąg reprezentujący adres URL pliku i $pathreprezentuje ścieżkę lokalną, do której plik zostanie zapisany.

Pamiętaj, że $pathmusi zawierać nazwę pliku; to nie może być tylko katalog.


32
Jak dotąd było to najlepsze proponowane rozwiązanie. Biorąc również pod uwagę, że wydaje się, że mogę przepisać go w jednym wierszu, ponieważ (new-object System.Net.WebClient).DownloadFile( '$url, $path)jest to najlepsza korespondencja, wgetjaką do tej pory widziałem. Dzięki!
jsalonen

3
Na marginesie możesz również zrobić to asynchronicznie, używając czegoś takiego (nowy obiekt System.Net.WebClient) .DownloadFileAsync (url, filePath)
James

Czy możemy pobrać konkretny tekst za pośrednictwem usługi Webclient i wysłać do notatnika? dzięki
Mowgli,

6
Tak, działa to od razu po wyjęciu z pudełka w systemie Windows 7 ( dostarczanym z PowerShell 2.0 ). Próbka: $client.DownloadFile( "http://blog.stackexchange.com/", "c:/temp2/_Download.html")
Peter Mortensen

3
Aby uzyskać tylko adres URL i zignorować wyniki (np. Część skryptu rozgrzewającego IIS) użyj DownloadData:(new-object System.Net.WebClient).DownloadData($url) | Out-Null
BurnsBA

86

Jest Invoke-WebRequestw nadchodzącej wersji PowerShell 3:

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

9
cała elegancja dd...
gWaldo

1
@gWaldo, z którego żartujesz - korzystanie z niego jest przyjemnością (mówienie jako ktoś dopiero uczący się PS)
Jack Douglas

8
Mam na myśli, że -Outfileparametr wydaje się obcy, gdy można po prostu użyć >(do zastąpienia) lub >>(do dołączenia) do pliku.
gWaldo

5
@gWaldo, a nawet wydedukuj nazwę pliku z adresu URL, tak jak to wgetrobi :)
Peltier

5
A od PS 4.0 wgeti curldomyślnie są przypisane do Invoke-WebRequest( iwr): D
Bob

18

To trochę bałagan, ale jest ten post na blogu, który zawiera instrukcje dotyczące pobierania plików.

Alternatywnie (i to polecam) możesz użyć BITS:

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

Pokazuje postępy i pobiera plik do bieżącego katalogu.


3
Usługa BITS opiera się na wsparciu po stronie serwera, jeśli jest dostępna, działa to w tle i można uzyskać aktualizacje postępu za pomocą innych poleceń cmdlet.
Richard

2
Próbowałem pobrać google.com , ale dostaję tylko Start-BitsTransfer : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)). Jestem zdziwiony: |
jsalonen

1
@ jsalonen Myślę, że BITS pobierze tylko pliki, a nie strony. Jak mówi Richard, polega on na pewnej obsłudze po stronie serwera (choć nie sądzę, że jest to specyficzne dla Microsoft).
Matthew Steeples,

Rozumiem i myślę, że mam sens w używaniu BITS, jednak nie tego tu szukam.
jsalonen

6

One-liner PowerShell V4:

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

lub

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

Jest to po prostu Warren (niesamowity) jednowierszowy V3 (dzięki za to!) - z drobną zmianą, aby działał w V4 PowerShell.

Jednowierszowy Warren - który po prostu używa wgetzamiast iwr- powinien nadal działać dla V3 (Przynajmniej, jak sądzę; chociaż go nie testowałem). Tak czy siak. Ale podczas próby uruchomienia go w programie PowerShell V4 (tak jak próbowałem) zobaczysz, że PowerShell nie może zostać rozpoznany wgetjako poprawny cmdlet / program.

Dla zainteresowanych, to jest - jak wybrałem z komentarza Boba w odpowiedzi na zaakceptowaną odpowiedź (dzięki, człowieku!) - ponieważ od PowerShell V4, wgeti curlsą aliasy Invoke-WebRequest, ustawione iwrdomyślnie . Dlatego wgetnie można go rozwiązać (jak również curlnie może tutaj działać) .


4

Oto funkcja PowerShell, która rozwiązuje krótkie adresy URL przed pobraniem pliku

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

Użyj go w ten sposób, aby pobrać plik do bieżącego folderu:

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

Lub, aby pobrać plik do określonego folderu:

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

2

Poniższa funkcja otrzyma adres 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)
}

Kilka komentarzy:

  1. Ostatnie 4 wiersze są potrzebne tylko wtedy, gdy jesteś za uwierzytelniającym serwerem proxy. Dla prostego użycia (New-Object Net.WebClient).DownloadFile($url, $path)działa dobrze.
  2. Ścieżka musi być bezwzględna, ponieważ pobieranie nie odbywa się w bieżącym katalogu, więc ścieżki względne spowodują, że gdzieś się zgubisz.
  3. if (!$path) {...}Sekcja obsługuje prosty przypadek, gdy po prostu chcesz pobrać plik do bieżącego katalogu, używając nazwy podanej w adresie URL.

1

Użyj powłoki bash systemu Windows 10, która zawiera wget po skonfigurowaniu funkcji systemu Windows.

Jak zainstalować powłokę bash Ubuntu w systemie Windows:

YouTube: Uruchamianie Bash na Ubuntu w systemie Windows!

Dokumentacja podsystemu Windows dla systemu Linux


1
Zastanów się nad dodaniem cytowanego odniesienia do tej odpowiedzi na poparcie tego, co podałeś na wypadek, gdyby link kiedykolwiek umarł, aby treść odpowiedzi była nadal dostępna, która jest obecnie dostępna tylko za pośrednictwem tego linku zgodnie z Twoją sugestią.
Pimp Juice IT

0

Jeśli twój system Windows jest wystarczająco nowy (jak wersja 1809 lub nowsza), dostępna jest „prawdziwa” lokówka. curl ma opcję wiersza polecenia „-O” (wielka litera O; mała litera nie zrobi tego samego!) Opcja „-O”, alternatywnie „--remote-name” informuje curl, że zapisany plik otrzymuje taka sama nazwa jak część nazwy pliku w adresie URL.

Należy uruchomić to jako „curl.exe”, aby odróżnić go od „curl” Alias ​​dla „Invoke-WebRequest”. Nawiasem mówiąc, działa w cmd.exe bez zmian.

Korzystając z tego samego przykładu, co w innej odpowiedzi tutaj

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

(Witryna nie pozwoli mi dodać tego jako komentarza, ponieważ najwyraźniej potrzebuję do tego większej „reputacji” - więc otrzymuje nową odpowiedź)


0

Invoke-WebRequest z parametrem -outfile oczekuje ciągu, więc jeśli nazwa pliku zaczyna się od liczby, a nie jest zawarta w cudzysłowach, plik wyjściowy nie jest tworzony.

na przykład. Invoke-WebRequest -Uri "http://www.google.com/" -outfile "2.pdf"

Nie wpływa to na nazwy plików zaczynające się na literę.


To rozwiązanie jest wspomniane w innych odpowiedziach ( wgetjest to alias Invoke-WebRequesti jedno podobne do powyższego)
bertieb

Celem odpowiedzi było podkreślenie notatki. Żadna z odpowiedzi nie dotyczy utworzenia pliku z powodu błędu składniowego.
Zimba

To naprawdę powinien być komentarz do innych odpowiedzi [s]
bertieb

Ta odpowiedź nie jest podana w innych odpowiedziach ani podobna do powyższej.
Zimba

-1

To powinno pomóc ci obejść rzeczy zainicjowane bez przeglądarki. Zwróć uwagę na parametr „-UseBasicParsing”.

Invoke-WebRequest http://localhost -UseBasicParsing

(1) Co to jest „rzeczy inicjowane bez przeglądarki”? (2) Zauważ, że w zaakceptowanej odpowiedzi już wspomniano -UseBasicParsing.
Scott
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.