PowerShell Set-Content และ Out-File - ความแตกต่างคืออะไร


90

ใน PowerShell ความแตกต่างระหว่างOut-FileและSet-Contentอย่างไร หรือAdd-ContentและOut-File -append?

ฉันได้พบถ้าผมใช้ทั้งกับไฟล์เดียวกันข้อความเป็นอย่างmojibaked

(คำถามรองลงมา: >เป็นนามแฝงOut-Fileใช่ไหม?)

คำตอบ:


96

นี่คือบทสรุปของสิ่งที่ฉันได้อนุมานหลังจากสัมผัสกับ PowerShell ไม่กี่เดือนและการทดลองทางวิทยาศาสตร์บางอย่าง ฉันไม่เคยพบสิ่งนี้ในเอกสาร :(

[ อัปเดต:ตอนนี้ส่วนใหญ่ดูเหมือนจะได้รับการบันทึกไว้ดีกว่า]

อ่านและเขียนการล็อก

ในขณะที่Out-Fileกำลังทำงานแอปพลิเคชันอื่นสามารถอ่านไฟล์บันทึกได้

ในขณะที่Set-Contentกำลังทำงานแอปพลิเคชันอื่น ๆ จะไม่สามารถอ่านไฟล์บันทึกได้ ดังนั้นอย่าใช้Set-Contentเพื่อบันทึกคำสั่งที่ทำงานเป็นเวลานาน

การเข้ารหัส

Out-Fileบันทึกในการเข้ารหัสUnicode( UTF-16LE) โดยค่าเริ่มต้น (แม้ว่าจะสามารถระบุได้) ในขณะที่Set-Contentค่าเริ่มต้นเป็นASCII( US-ASCII) ใน PowerShell 3+ (อาจระบุได้ด้วย) ใน PowerShell เวอร์ชันก่อนหน้านี้Set-Contentเขียนเนื้อหาในการDefaultเข้ารหัส (ANSI)

หมายเหตุบรรณาธิการ : PowerShell ในเวอร์ชัน 5.1 ยังคงใช้ค่าเริ่มต้นของการDefaultเข้ารหัสเฉพาะวัฒนธรรม("ANSI") แม้ว่าเอกสารจะอ้างว่าเป็นอย่างไร หาก ASCII เป็นตัวละครค่าเริ่มต้นไม่ใช่ ASCII เช่นüจะถูกแปลงเป็นตัวอักษร ?แต่ที่ไม่ได้กรณีที่: อัตราผลตอบแทน'ü' | Set-Content tmp.txt; (Get-Content tmp.txt) -eq '?'$False

PS > $null | out-file outed.txt
PS > $null | set-content set.txt
PS > md5sum *
f3b25701fe362ec84616a93a45ce9998 *outed.txt
d41d8cd98f00b204e9800998ecf8427e *set.txt

ซึ่งหมายความว่าค่าเริ่มต้นของคำสั่งสองคำสั่งไม่เข้ากันและการผสมกันจะทำให้ข้อความเสียหายดังนั้นควรระบุการเข้ารหัส

การจัดรูปแบบ

ดังที่ Bartek อธิบายOut-Fileบันทึกการจัดรูปแบบแฟนซีของเอาต์พุตดังที่เห็นในเทอร์มินัล ดังนั้นในโฟลเดอร์ที่มีสองไฟล์คำสั่งdir | out-file out.txtจะสร้างไฟล์ที่มี 11 บรรทัด

ในขณะที่Set-Contentบันทึกการแสดงที่ง่ายกว่า ในโฟลเดอร์นั้นมีสองไฟล์คำสั่งdir | set-content sc.txtจะสร้างไฟล์ที่มีสองบรรทัด ในการจำลองเอาต์พุตในเทอร์มินัล:

PS > dir | ForEach-Object {$_.ToString()}
out.txt
sc.txt

ฉันเชื่อว่าการจัดรูปแบบนี้มีผลต่อการแบ่งบรรทัด แต่ฉันยังอธิบายไม่ได้

การสร้างไฟล์

Set-Contentไม่สามารถสร้างไฟล์เปล่าได้อย่างน่าเชื่อถือเมื่อOut-Fileต้องการ:

ในโฟลเดอร์ว่างคำสั่งdir | out-file out.txtจะสร้างไฟล์ในขณะที่dir | set-content sc.txtไม่มี

ตัวแปรท่อ

Set-Contentใช้ชื่อไฟล์จากไปป์ไลน์ ช่วยให้คุณสามารถตั้งค่าเนื้อหาของไฟล์จำนวนหนึ่งเป็นค่าคงที่

Out-Fileรับข้อมูลจากท่อ อัปเดตเนื้อหาของไฟล์เดียว

พารามิเตอร์

Set-Content ประกอบด้วยพารามิเตอร์เพิ่มเติมดังต่อไปนี้:

  • ไม่รวม
  • กรอง
  • รวม
  • PassThru
  • กระแส
  • UseTransaction

Out-File ประกอบด้วยพารามิเตอร์เพิ่มเติมดังต่อไปนี้:

  • ผนวก
  • NoClobber
  • ความกว้าง

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับพารามิเตอร์เหล่านี้โปรดดูความช่วยเหลือ เช่นget-help out-file -parameter append.


4
Set-Contentการเข้ารหัสเริ่มต้น: แปลเป็น(Get-Culture).Textinfo.ANSICodePage(Windows 8.1, Powershell 4.0, CurrentCulture cs-CZ, CurrentUICulture en-GB, ANSICodePage 1250, OEMCodePage 852ทดสอบโดยใช้'řž'สตริงที่มีรหัสต่างกันในหน้าโค้ดด้านบน)
JosefZ

นอกจากนี้โปรดทราบว่าOut-Fileมีปัญหากับสายยาวในบางสถานการณ์ ตัวอย่างเช่น: $x = [pscustomobject]@{A=('a' * 500); B=('b' * 500)}; $x | Out-File -Path myfile.txt.
Bacon Bits

17

Out-Fileมีลักษณะการทำงานของการเขียนทับเส้นทางเอาต์พุตเว้นแต่จะมีการตั้งค่าสถานะ-NoClobberและ / หรือ-Appendแฟล็ก Add-Contentจะต่อท้ายเนื้อหาหากเส้นทางเอาต์พุตมีอยู่แล้วตามค่าเริ่มต้น (ถ้าทำได้) ทั้งสองจะสร้างไฟล์หากไม่มีอยู่แล้ว

ความแตกต่างที่น่าสนใจอีกประการหนึ่งคือAdd-Contentจะสร้างไฟล์ที่เข้ารหัส ASCII ตามค่าเริ่มต้นและOut-Fileจะสร้างไฟล์ที่เข้ารหัส endian unicode เล็กน้อยตามค่าเริ่มต้น

>เป็นนามแฝงOut-Fileน้ำตาลประโยคสำหรับ ซึ่งOut-Fileมีการตั้งค่าพารามิเตอร์ที่กำหนดไว้ล่วงหน้า


ขอบคุณการทราบความแตกต่างของการเข้ารหัสมีประโยชน์ คุณไม่ถูกต้องถ้าคุณทำecho "" > $null | Add-Content abc.txtมันไม่ได้สร้างไฟล์abc.txtในขณะที่ออกจากไฟล์จะ
พันเอก Panic

@MattHickford นั่นเป็นตัวอย่างกรณีขอบแปลก ๆ รหัสนั้นไปป์เป็น $ null จึงAdd-Contentไม่ได้รับอะไรเลย หากAdd-Contentไม่ได้รับอะไรทำไมจึงควรสร้างไฟล์? ในทางกลับกันอาจมีการถามคำถามเดียวกันกับ Out-File
Andy Arismendi

ความแตกต่างมีความสำคัญกับฉันgci $folder | Out-File log.txt ; cat log.txtในขณะที่gci $folder | Add-Content log.txt ; cat log.txtเกิดขึ้น
พันเอก Panic

@MattHickford ฉันอาจจะตรวจสอบให้แน่ใจว่ามีไฟล์อยู่ก่อนที่จะพยายามประมวลผล น่าจะเป็นนิสัยที่ดีสำหรับทุกภาษา
Andy Arismendi

ความแตกต่างอีกประการหนึ่งคือในขณะSet-Contentที่ใช้งานไฟล์จะไม่สามารถใช้งานได้กับแอปพลิเคชันอื่น
พันเอก Panic

10

ฉันไม่เห็นด้วย ... :)

  1. Out-File มี -Append (-NoClober อยู่ที่นั่นเพื่อหลีกเลี่ยงการเขียนทับ) ที่จะเพิ่มเนื้อหา แต่นี่ไม่ใช่สัตว์ร้ายตัวเดียวกัน
  2. คำสั่ง | Add-Content จะใช้เมธอด. ToString () ในการป้อนข้อมูล Out-File จะใช้การจัดรูปแบบเริ่มต้น

ดังนั้น:

ls | Add-Content test.txt

และ

ls | Out-File test.txt

จะให้ผลลัพธ์ที่แตกต่างกันโดยสิ้นเชิง

และไม่ ">" ไม่ใช่นามแฝง แต่เป็นตัวดำเนินการเปลี่ยนเส้นทาง (เช่นเดียวกับในเชลล์อื่น ๆ ) และมีข้อ จำกัด ที่ร้ายแรงมาก ... มันจะตัดเส้นแบบเดียวกับที่แสดง Out-File มีพารามิเตอร์ -Width ที่ช่วยคุณหลีกเลี่ยงสิ่งนี้ นอกจากนี้ด้วยตัวดำเนินการเปลี่ยนเส้นทางคุณไม่สามารถตัดสินใจได้ว่าจะใช้การเข้ารหัสใด

HTH Bartek


3
มันเป็นนามแฝงในความหมายว่า>และ Out-File คือสิ่งเดียวกัน พวกเขาเรียกรหัสเดียวกัน จาก PowerShell in Action Second Edition ของ Bruce Payette (Kindle Locations 4646):In fact, myScript > file.txt is just “syntactic sugar” for myScript | out-file -path file.txt In some cases, you’ll want to use Out-File directly because it gives you more control over the way the output is written.
Andy Arismendi

1
จุดดีเกี่ยวกับการจัดรูปแบบเริ่มต้น (Out-File) กับ ToString (Add-Content)
Andy Arismendi

ประเด็นของฉันคือแม้ว่าโดยทั่วไปทั้งสองจะทำเหมือนกัน แต่นามแฝงก็มีความหมายใน PowerShell ... ดังนั้นฉันจะไม่ใช้คำนี้เพื่ออธิบายความสัมพันธ์ระหว่างสิ่งเหล่านี้ด้วย .. ;) นามแฝงแทนที่คำสั่งในกรณีนี้ควรสร้างไวยากรณ์ : ls | > file.txt ได้ เห็นได้ชัดว่ามันใช้ไม่ได้ ...
BartekB

1
การจัดรูปแบบเริ่มต้นเป็นวิธีการนำเสนอวัตถุที่กำหนดในคอนโซล cmdlet หลัก / ประเภทออบเจ็กต์ส่วนใหญ่มีการจัดรูปแบบข้อมูลเมตาที่แจ้งให้ PowerShell ทราบถึงวิธีการแสดงในรูปแบบที่ใช้งานง่าย กล่าวอีกนัยหนึ่ง: การไปป์ผลลัพธ์ของคำสั่งไปยัง Out-File สามารถใช้เพื่อบันทึกผลลัพธ์ของคำสั่งไปยังไฟล์โดยไม่สูญเสียการจัดรูปแบบที่ทำโดย PowerShell
BartekB

2
ใช่ฉันคิดว่ามันเป็นความแตกต่างที่สำคัญที่ไม่ได้เป็นที่แน่นอนสำหรับเทียบเท่า> out-fileถ้าคุณตั้งค่าก็จะถูกละเลยโดย$PSDefaultParameterValues["Out-File:Encoding"] = "UTF8" >
wisbucky

3

Set-Contentรองรับ-Encoding Byteในขณะที่Out-Fileไม่

ดังนั้นเมื่อคุณต้องการที่จะเขียนข้อมูลไบนารีหรือผลของการไปยังแฟ้มที่คุณควรใช้Text.Encoding#GetBytes()Set-Content


0

Out-file -append หรือ ">>" สามารถผสมการเข้ารหัสสองรายการในไฟล์เดียวกันได้ แม้ว่าไฟล์เดิมจะเป็น ascii หรือ ansi แต่ก็จะเพิ่ม Unicode ไว้ที่ด้านล่างของไฟล์โดยค่าเริ่มต้น Add-content จะตรวจสอบการเข้ารหัสและจับคู่ก่อนต่อท้าย Btw ค่าเริ่มต้น export-csv เป็น ascii (ไม่มีสำเนียง) และ set-content / add-content ไปยัง ansi


0

ต้องการเพิ่มความแตกต่างในการเข้ารหัส:

Windows พร้อม PowerShell 5.1:

  • Out-File - การเข้ารหัสเริ่มต้นคือ utf-16le
  • ชุดเนื้อหา - การเข้ารหัสเริ่มต้นคือ us-ascii

Linux พร้อม PowerShell 7.1:

  • Out-File - การเข้ารหัสเริ่มต้นคือ us-ascii
  • ชุดเนื้อหา - การเข้ารหัสเริ่มต้นคือ us-ascii
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.