Родная альтернатива wget в Windows PowerShell?


284

Я знаю, что могу загрузить и установить вышеупомянутую библиотеку (wget для Windows), но у меня такой вопрос:

В Windows PowerShell есть собственная альтернатива wget?

Мне нужно wgetпросто получить файл с данного URL с помощью HTTP GET. Например:

wget http://www.google.com/

Ответы:


236

Вот простой PS 3.0 и более поздний однострочный, который работает и не требует большого количества PS barf:

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

Обратите внимание, что:

  • wget это псевдоним для Invoke-WebRequest
  • Invoke-WebRequest возвращает HtmlWebResponseObject , который содержит множество полезных свойств для разбора HTML, таких как ссылки, изображения, формы, поля ввода и т. Д., Но в этом случае мы просто используем необработанный контент
  • Содержимое файла хранится в памяти перед записью на диск, что делает этот подход непригодным для загрузки больших файлов
  • При установке Windows Server Core вам нужно записать это как

    wget http://blog.stackexchange.com/ -UseBasicParsing -OutFile out.html
    
  • До 20 сентября 2014 года я предложил

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

    как ответ. Однако это работает не во всех случаях, так как >оператор (который является псевдонимом Out-File) преобразует ввод в Unicode.

Если вы используете Windows 7, вам необходимо установить версию 4 или более новую платформу Windows Management Framework.

Возможно, вы обнаружите, что выполнение команды $ProgressPreference = "silentlyContinue"before Invoke-WebRequestзначительно улучшит скорость загрузки больших файлов; эта переменная контролирует, отображается ли пользовательский интерфейс прогресса.


3
Теперь это правильный ответ, и я случайно наткнулся на wget, проверяя, установлен ли я на самом деле. Раздражает, что он не может легко получить имя файла (вы должны указать его в перенаправлении вывода), но этот параметр имеет лучший интерфейс, чем реальный wget (по моему мнению), так что это так.
Мэтью Шарли

13
Но Windows 7 поставляется только с PowerShell 2.0 , и результатом будет «Термин« Invoke-WebRequest »не распознается как имя командлета, ...».
Питер Мортенсен

16
Справедливое предупреждение: этот метод помещает все содержимое файла в память перед записью его в файл. Это не очень хорошее решение для загрузки больших файлов.
im_nullable

2
@im_nullable, хороший звонок - я добавил это к посту.
Уоррен Румак,

1
@dezza Я обновил ответ другим подходом. Попробуйте снова.
Уоррен Румак

181

Если вам просто нужно получить файл, вы можете использовать метод DownloadFile объекта WebClient :

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

Где $urlстрока, представляющая URL-адрес файла и $pathпредставляющая локальный путь, в который будет сохранен файл.

Обратите внимание, что $pathдолжно включать имя файла; это не может быть просто каталог.


32
До сих пор это было лучшее предлагаемое решение. Также, учитывая, что, кажется, я могу переписать его в формате одной строки, поскольку (new-object System.Net.WebClient).DownloadFile( '$url, $path)это лучшее соответствие, которое wgetя видел до сих пор. Спасибо!
jsalonen

3
Как примечание вы также можете сделать это асинхронно, используя что-то вроде (new-object System.Net.WebClient) .DownloadFileAsync (url, filePath)
Джеймс

Можем ли мы получить определенный текст через Webclient и отправить его в блокнот? спасибо
Маугли

6
Да, это работает из коробки на Windows 7 ( который поставляется с PowerShell 2.0 ). Образец: $client.DownloadFile( "http://blog.stackexchange.com/", "c:/temp2/_Download.html")
Питер Мортенсен

3
Для получения только URL-адреса и игнорирования результатов (например, части сценария разогрева IIS) используйте DownloadData:(new-object System.Net.WebClient).DownloadData($url) | Out-Null
BurnsBA

85

В Invoke-WebRequestследующей версии PowerShell 3:

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

9
вся элегантность dd...
gWaldo

1
@gWaldo, ты шутишь - это радость для использования (говоря как кто-то, кто только учится PS)

8
Я просто имею в виду, что -Outfileпараметр кажется посторонним, когда вы можете просто использовать >(перезаписать) или >>(добавить) в файл.
gWaldo

5
@gWaldo или даже вывести имя файла из URL, как это wgetделает :)
Пельтье

5
И начиная с PS 4.0, wgetи по умолчанию curlпсевдоним Invoke-WebRequest( iwr): D
Боб

18

Это немного грязно, но есть этот пост в блоге, который дает вам инструкции для загрузки файлов.

В качестве альтернативы (и это я бы порекомендовал) вы можете использовать биты:

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

Он покажет прогресс и загрузит файл в текущий каталог.


3
BITS полагается на поддержку на стороне сервера, если доступно, это работает в фоновом режиме, и вы можете получать обновления прогресса с другими командлетами.
Ричард

2
Я пытался получить google.com , но все, что я получил, это Start-BitsTransfer : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)). Я озадачен: |
jsalonen

1
@jsalonen Я думаю, что BITS будет загружать только файлы, а не страницы. Как говорит Ричард, он опирается на некоторую поддержку на стороне сервера (хотя я не думаю, что это специфично для Microsoft).
Мэтью Стиплз

Я вижу и думаю, что понимаю смысл использования BITS, однако здесь дело не в том, что я ищу.
jsalonen

6

PowerShell V4 One-liner:

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

или же

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

Это в основном Уоррен (удивительный) однострочный V3 (спасибо за это!) - с небольшим изменением, чтобы заставить его работать в PowerShell V4.

Однострочник Уоррена - который просто использует, wgetа не iwr- должен по-прежнему работать для V3 (по крайней мере, я думаю, хотя и не проверял его). Так или иначе. Но при попытке выполнить его в PowerShell V4 (как я пытался) вы увидите, что PowerShell не удается преобразовать wgetв действительный командлет / программу.

Для тех, кто заинтересован, это - как я понял из комментария Боба в ответ на принятый ответ (спасибо, мужик!) - потому чтоwgetcurlInvoke-WebRequestiwr начиная с PowerShell V4 и для которого назначены псевдонимы , установлено по умолчанию . Таким образом, wgetне может быть решена (а также curlне может работать здесь) .


4

Вот функция PowerShell, которая разрешает короткие URL-адреса перед загрузкой файла

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

Используйте это так, чтобы загрузить файл в текущую папку:

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

Или загрузить файл в указанную папку:

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

2

Следующая функция получит 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)
}

Некоторые комментарии:

  1. Последние 4 строки нужны, только если вы находитесь за прокси-сервером аутентификации. Для простого использования (New-Object Net.WebClient).DownloadFile($url, $path)работает нормально.
  2. Путь должен быть абсолютным, так как загрузка не выполняется в текущем каталоге, поэтому относительные пути приведут к потере загрузки.
  3. В этом if (!$path) {...}разделе рассматривается простой случай, когда вы просто хотите загрузить файл в текущий каталог, используя имя, указанное в URL.

1

Используйте оболочку Windows 10 bash, которая включает wget после настройки Windows.

Как установить оболочку Ubuntu Bash на Windows:

YouTube: запуск Bash в Ubuntu под Windows!

Документация по подсистеме Windows для Linux


1
Подумайте о том, чтобы добавить к этому ответу некоторую цитируемую ссылку, подтверждающую то, что вы заявляете на случай, если ссылка когда-либо умрет, чтобы содержание ответа все еще было доступно, и в настоящее время доступно только по этой ссылке для вашего предложения.
Сок Pimp IT

0

Если ваша Windows достаточно новая (например, версия 1809 или новее), есть «настоящий» локоть. curl имеет параметр командной строки "-O" (заглавная буква O; строчная буква не будет делать то же самое!) Опция "-O", альтернатива "--remote-name" сообщает curl, что сохраненный файл получает то же имя, что и часть имени файла в URL.

Нужно запустить это как "curl.exe", чтобы отличить его от псевдонима "curl" для "Invoke-WebRequest". Кстати, он работает в cmd.exe без изменений.

Используя тот же пример, что и в другом ответе здесь

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

(Сайт не позволит мне добавить это в качестве комментария, так как мне, очевидно, нужно больше «репутации» для этого - поэтому он получает новый ответ)


0

Invoke-WebRequest с параметром -outfile ожидает строку, поэтому, если ваше имя файла начинается с цифры и не заключено в кавычки, выходной файл не создается.

например. Invoke-WebRequest -Uri "http://www.google.com/" -outfile "2.pdf"

Это не влияет на имена файлов, начинающиеся с буквы.


Это решение упоминается в других ответах ( wgetявляется псевдонимом Invoke-WebRequestи аналогичен приведенному выше)
bertieb

Суть ответа заключалась в том, чтобы подчеркнуть примечание. Ни один из ответов не касается созданного файла из-за синтаксической ошибки.
Зимба

Это действительно должен быть комментарий к другому ответу [s]
bertieb

Этот ответ не приводится в других ответах и ​​не похож на приведенный выше.
Зимба

-1

Это должно работать для вас, чтобы обойти браузер без инициализации вещи. Обратите внимание на параметр -UseBasicParsing.

Invoke-WebRequest http://localhost -UseBasicParsing

(1) Что такое «без инициализации браузера»? (2) Обратите внимание, что принятый ответ уже упоминает -UseBasicParsing.
Скотт
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.