Natywna alternatywa dla wget w Windows PowerShell?

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.

Warren Rumak
źródło
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.

Podróżujący facet techniczny
źródło
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
użytkownik4514
źródło
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.

Matthew Steeples
źródło
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ć) .

eyecatchUp
źródło
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  
użytkownik25986
źródło
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.
Paul Moore
źródło
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

Miloud Eloumri
źródło
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ź)

Dweia
źródło
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ę.

Zimba
źródło
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
Joe Healy
źródło
(1) Co to jest „rzeczy inicjowane bez przeglądarki”? (2) Zauważ, że w zaakceptowanej odpowiedzi już wspomniano -UseBasicParsing.
Scott