ทางเลือกอื่นของ wget ใน Windows PowerShell?


283

ฉันรู้ว่าฉันสามารถดาวน์โหลดและติดตั้งไลบรารี่ aformentioned (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 ที่มีประโยชน์มากมายเช่นลิงค์รูปภาพแบบฟอร์ม InputFields เป็นต้น แต่ในกรณีนี้เราแค่ใช้เนื้อหาดิบ
  • เนื้อหาไฟล์ถูกเก็บไว้ในหน่วยความจำก่อนที่จะเขียนลงดิสก์ทำให้วิธีการนี้ไม่เหมาะสำหรับการดาวน์โหลดไฟล์ขนาดใหญ่
  • ในการติดตั้ง 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"ก่อนหน้าInvoke-WebRequestนี้จะช่วยเพิ่มความเร็วในการดาวน์โหลดด้วยไฟล์ขนาดใหญ่ ตัวแปรนี้ควบคุมว่าจะแสดง UI ความคืบหน้าหรือไม่


3
นี่เป็นคำตอบที่ถูกต้องแล้วและฉันพบกับการทดสอบโดยไม่ตั้งใจถ้าฉันติดตั้ง wget จริง น่ารำคาญที่ไม่สามารถรับชื่อไฟล์ได้ง่าย (คุณต้องระบุไว้ในการเปลี่ยนเส้นทางเอาต์พุต) แต่ตัวเลือกนี้มี UI ที่ดีกว่าตัวจริง (ในความคิดของฉัน) ดังนั้นจึงมี
Matthew Scharley

13
แต่Windows 7 มาพร้อมกับ PowerShell 2.0เท่านั้นและผลลัพธ์จะเป็น "คำว่า 'Invoke-WebRequest' ไม่รู้จักเป็นชื่อของ cmdlet, ... "
Peter Mortensen

16
คำเตือนที่เป็นธรรม: วิธีนี้จะนำเนื้อหาทั้งหมดของไฟล์ลงในหน่วยความจำก่อนที่จะเขียนลงในไฟล์ นี่ไม่ใช่ทางออกที่ดีสำหรับการดาวน์โหลดไฟล์ขนาดใหญ่
im_nullable

2
@im_nullable โทรได้ดี - ฉันได้เพิ่มไปยังโพสต์แล้ว
Warren Rumak

1
@dezza ฉันได้อัปเดตคำตอบด้วยวิธีการอื่นแล้ว ลองอีกครั้ง.
Warren Rumak

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)
James

เราสามารถดึงข้อความเฉพาะผ่านทาง Webclient และไปยัง notepad ได้หรือไม่ ขอบคุณ
Mowgli

6
ใช่สิ่งนี้ใช้ได้นอกกรอบบน Windows 7 ( ที่มาพร้อมกับ PowerShell 2.0 ) ตัวอย่าง: $client.DownloadFile( "http://blog.stackexchange.com/", "c:/temp2/_Download.html")
Peter Mortensen

3
เพียงรับ URL และละเว้นผลลัพธ์ (เช่นเป็นส่วนหนึ่งของสคริปต์ IIS warmup) ให้ใช้ DownloadData:(new-object System.Net.WebClient).DownloadData($url) | Out-Null
BurnsBA

86

มีอยู่Invoke-WebRequestใน PowerShell เวอร์ชัน 3 ที่จะมาถึง:

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

9
ความงดงามทั้งหมดของdd...
gWaldo

1
@ gWaldo คุณล้อเล่นนี่เป็นความสุขที่ได้ใช้ (พูดกับคนที่เพิ่งเรียนรู้ PS)
Jack Douglas

8
ฉันแค่หมายถึงว่า-Outfileพารามิเตอร์ดูเหมือนภายนอกเมื่อคุณสามารถใช้>(เพื่อเขียนทับ) หรือ>>(เพื่อผนวก) ไปยังไฟล์
gWaldo

5
@gWaldo หรือแม้กระทั่งการอนุมานชื่อไฟล์จาก URL เช่นเดียวกับwgetไม่ :)
Peltier

5
และในฐานะของ PS 4.0 wgetและได้curlรับการตั้งค่าเป็นInvoke-WebRequest( iwr) โดยค่าเริ่มต้น: D
Bob

18

มันยุ่งเล็กน้อย แต่มีโพสต์บล็อกนี้ซึ่งให้คำแนะนำในการดาวน์โหลดไฟล์

อีกวิธีหนึ่ง (และนี่คือสิ่งที่ฉันแนะนำ) คุณสามารถใช้ BITS:

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

มันจะแสดงความคืบหน้าและจะดาวน์โหลดไฟล์ไปยังไดเรกทอรีปัจจุบัน


3
BITS อาศัยการสนับสนุนที่ส่วนท้ายของเซิร์ฟเวอร์หากมีให้ใช้งานได้ในพื้นหลังและคุณสามารถรับการอัปเดตความคืบหน้ากับ cmdlet อื่น ๆ
Richard

2
ผมพยายามที่จะดึงข้อมูลgoogle.comStart-BitsTransfer : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))แต่ทั้งหมดที่ฉันได้รับคือ ฉันงงงวย: |
jsalonen

1
@ jsalonen ฉันคิดว่า BITS จะดาวน์โหลดไฟล์มากกว่าหน้าเท่านั้น ริชาร์ดกล่าวว่ามันขึ้นอยู่กับการสนับสนุนด้านเซิร์ฟเวอร์บางอย่าง (แม้ว่าฉันไม่คิดว่ามันจะเฉพาะเจาะจงกับ Microsoft)
Matthew Steeples

ฉันเห็นและฉันคิดว่าฉันได้รับจุดในการใช้ BITS แต่มันไม่ใช่สิ่งที่ฉันกำลังมองหาที่นี่
jsalonen

6

PowerShell V4 หนึ่งซับ:

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

หรือ

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

นี่เป็นหนึ่งในสายการบิน (น่ากลัว) ของ V3 Warren (ขอบคุณสำหรับสิ่งนี้!) - ด้วยการเปลี่ยนแปลงเพียงเล็กน้อยเพื่อให้มันทำงานใน V4 PowerShell

สายการบินเดียวของ Warrenซึ่งใช้ง่ายwgetกว่าiwr- ควรใช้กับV3 ได้ (อย่างน้อยฉันก็เดาได้; ไม่ได้ทดสอบเลย) อย่างไรก็ตาม. แต่เมื่อพยายามที่จะดำเนินการในV4 PowerShell (อย่างที่ฉันพยายาม) คุณจะเห็น PowerShell ล้มเหลวในการแก้ไขwgetเป็น cmdlet / โปรแกรมที่ถูกต้อง

สำหรับผู้ที่สนใจที่เป็น - เป็นฉันหยิบขึ้นมาจากความคิดเห็นของบ๊อบในการตอบคำตอบที่ได้รับการยอมรับ (ขอบคุณคน!) - เพราะเป็นของ PowerShell V4, wgetและcurlมีชื่อว่าInvoke-WebRequestตั้งค่าiwrตามค่าเริ่มต้น ดังนั้นจึง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 ซึ่งรวมถึง wget เมื่อตั้งค่าคุณสมบัติ windows แล้ว

วิธีติดตั้ง Ubuntu bash shell บน Windows:

YouTube: การใช้ Bash บน Ubuntu บน Windows!

ระบบย่อย Windows สำหรับเอกสารคู่มือ Linux


1
ลองเพิ่มการอ้างอิงที่ยกมาให้กับคำตอบนี้เพื่อสนับสนุนสิ่งที่คุณระบุในกรณีที่ลิงก์นั้นเคยตายดังนั้นเนื้อหาคำตอบจะยังคงมีอยู่ซึ่งปัจจุบันมีให้ผ่านทางลิงค์นั้นตามคำแนะนำของคุณเท่านั้น
Pimp Juice IT

0

หาก Windows ของคุณใหม่พอ (เช่นรุ่น 1809 หรือใหม่กว่า) แสดงว่ามี "ของจริง" ขดอยู่ curl มีตัวเลือกบรรทัดคำสั่ง "-O" (อักษรตัวใหญ่ O; อักษรตัวเล็กจะไม่ทำเช่นเดียวกัน!) ตัวเลือก "-O" หรืออีกทางหนึ่ง "--remote-name" จะบอก curl ว่าไฟล์ที่บันทึกได้รับ ชื่อเดียวกับส่วนชื่อไฟล์ของ URL

หนึ่งต้องเริ่มต้นนี้เป็น "curl.exe" เพื่อแยกแยะจาก Alias ​​"curl" สำหรับ "Invoke-WebRequest" บังเอิญมันทำงานใน cmd.exe โดยไม่มีการเปลี่ยนแปลง

ใช้ตัวอย่างเดียวกันกับในคำตอบอื่นที่นี่

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

(เว็บไซต์จะไม่อนุญาตให้ฉันเพิ่มสิ่งนี้เป็นความคิดเห็นเนื่องจากเห็นได้ชัดว่าฉันต้องการ "ชื่อเสียง" มากกว่านี้ - ดังนั้นจึงได้รับคำตอบใหม่)


0

เรียกใช้ WebRequest ด้วยพารามิเตอร์ -outfile คาดว่าจะมีสตริงดังนั้นหากชื่อไฟล์ของคุณเริ่มต้นด้วยตัวเลขและไม่อยู่ในเครื่องหมายคำพูดจะไม่มีการสร้างไฟล์เอาต์พุต

เช่น. Invoke-WebRequest -Uri "http://www.google.com/" -outfile "2.pdf"

สิ่งนี้จะไม่มีผลกับชื่อไฟล์ที่ขึ้นต้นด้วยตัวอักษร


การแก้ปัญหานี้ถูกกล่าวถึงในคำตอบอื่น ๆ ( wgetเป็นนามแฝงของInvoke-WebRequestและหนึ่งคล้ายกับข้างต้น)
bertieb

จุดสำคัญของคำตอบคือการเน้นบันทึก ไม่มีคำตอบใด ๆ ที่จัดการกับไฟล์ที่ไม่ถูกสร้างขึ้นเนื่องจากข้อผิดพลาดทางไวยากรณ์
Zimba

นั่นควรจะเป็นความเห็นในคำตอบอื่น ๆ [s]
bertieb

คำตอบนี้ไม่ได้ให้ไว้ในคำตอบอื่น ๆ หรือคล้ายกับคำตอบข้างต้น
Zimba

-1

สิ่งนี้น่าจะช่วยให้คุณหลีกเลี่ยงสิ่งที่เบราว์เซอร์เริ่มต้นได้ หมายเหตุพารามิเตอร์ "-UseBasicParsing"

Invoke-WebRequest http://localhost -UseBasicParsing

(1)“ ไม่มีเบราว์เซอร์เริ่มต้นสิ่ง” คืออะไร? (2) -UseBasicParsingโปรดทราบว่าคำตอบที่ได้รับการยอมรับแล้วกล่าว
สกอตต์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.