PowerShell Set-Content và Out-File - sự khác biệt là gì?


88

Trong PowerShell, sự khác biệt giữa Out-FileSet-Content? Hoặc Add-ContentOut-File -append?

Tôi đã phát hiện ra rằng nếu tôi sử dụng cả hai đối với cùng một tệp, văn bản hoàn toàn bị sai lệch .

(Một câu hỏi nhỏ thứ hai: >là một bí danh cho Out-File, phải không?)

Câu trả lời:


95

Dưới đây là bản tóm tắt những gì tôi đã suy luận, sau vài tháng trải nghiệm với PowerShell và một số thử nghiệm khoa học. Tôi chưa bao giờ tìm thấy bất kỳ điều nào trong số này trong tài liệu :(

[ Cập nhật: Phần lớn điều này bây giờ dường như được ghi lại tốt hơn.]

Khóa đọc và ghi

Trong khi Out-Fileđang chạy, một ứng dụng khác có thể đọc tệp nhật ký.

Trong khi Set-Contentđang chạy, các ứng dụng khác không thể đọc tệp nhật ký. Vì vậy, không bao giờ sử dụngSet-Content để ghi các lệnh chạy dài.

Mã hóa

Out-Filelưu trong mã hóa Unicode( UTF-16LE) theo mặc định (mặc dù điều này có thể được chỉ định), trong khi Set-Contentmặc định là ASCII( US-ASCII) trong PowerShell 3+ (điều này cũng có thể được chỉ định). Trong các phiên bản PowerShell trước đó, Set-Contentđã viết nội dung ở dạng Defaultmã hóa (ANSI).

Lưu ý của người biên tập : PowerShell kể từ phiên bản 5.1 vẫn mặc định là mã hóa dành riêng cho văn hóa Default("ANSI"), bất chấp những gì tài liệu tuyên bố. Nếu ASCII là mặc định, các ký tự không phải ASCII chẳng hạn üsẽ được chuyển đổi thành nghĩa đen ? , nhưng đó không phải là trường hợp: kết 'ü' | Set-Content tmp.txt; (Get-Content tmp.txt) -eq '?'quả $False.

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

Điều này có nghĩa là mặc định của hai lệnh không tương thích và việc trộn chúng sẽ làm hỏng văn bản, vì vậy hãy luôn chỉ định một mã hóa.

Định dạng

Như Bartek đã giải thích, Out-Filelưu định dạng ưa thích của đầu ra, như đã thấy trong thiết bị đầu cuối. Vì vậy, trong một thư mục có hai tệp, lệnh dir | out-file out.txttạo một tệp có 11 dòng.

Trong khi Set-Contenttiết kiệm một biểu diễn đơn giản hơn. Trong thư mục đó có hai tệp, lệnh dir | set-content sc.txttạo một tệp có hai dòng. Để mô phỏng đầu ra trong thiết bị đầu cuối:

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

Tôi tin rằng định dạng này có hậu quả là ngắt dòng, nhưng tôi chưa thể mô tả nó.

Tạo tệp

Set-Contentkhông đáng tin cậy tạo một tệp trống khi Out-File:

Trong một thư mục trống, lệnh dir | out-file out.txttạo một tệp, trong khi dir | set-content sc.txtthì không.

Biến đường ống

Set-Contentlấy tên tệp từ đường ống; cho phép bạn đặt một số nội dung của tệp thành một số giá trị cố định.

Out-Filelấy dữ liệu từ đường ống; cập nhật nội dung của một tệp duy nhất.

Thông số

Set-Content bao gồm các thông số bổ sung sau:

  • Loại trừ
  • Bộ lọc
  • Bao gồm
  • PassThru
  • Suối
  • UseTransaction

Out-File bao gồm các thông số bổ sung sau:

  • Nối
  • NoClobber
  • Chiều rộng

Để biết thêm thông tin về những thông số đó là gì, vui lòng tham khảo trợ giúp; vd get-help out-file -parameter append.


4
Set-Contentmã hóa mặc định: được dịch sang (Get-Culture).Textinfo.ANSICodePage(Windows 8.1, Powershell 4.0, CurrentCulture cs-CZ, CurrentUICulture en-GB, ANSICodePage 1250, OEMCodePage 852, được thử nghiệm bằng cách sử dụng 'řž'chuỗi với các mã khác nhau trong các trang mã trên).
JosefZ

Cũng lưu ý rằng Out-Filecó vấn đề với các dòng dài trong các tình huống nhất định. Ví dụ: $x = [pscustomobject]@{A=('a' * 500); B=('b' * 500)}; $x | Out-File -Path myfile.txt.
Bacon Bits

17

Out-Filecó hành vi ghi đè đường dẫn đầu ra trừ khi -NoClobbervà / hoặc -Appendcờ được đặt. Add-Contentsẽ thêm nội dung nếu đường dẫn đầu ra đã tồn tại theo mặc định (nếu có thể). Cả hai sẽ tạo tệp nếu tệp chưa tồn tại.

Một sự khác biệt thú vị khác là nó Add-Contentsẽ tạo một tệp được mã hóa ASCII theo mặc định và Out-Filesẽ tạo một tệp được mã hóa unicode nhỏ theo mặc định.

>một đường cú pháp bí danh cho Out-File. Nó Out-Filevới một số cài đặt thông số được xác định trước.


Cảm ơn, biết sự khác biệt về mã hóa là rất hữu ích. Bạn không hoàn toàn đúng, nếu bạn làm điều echo "" > $null | Add-Content abc.txtđó sẽ không tạo ra tệp abc.txt, trong khi Out-File sẽ tạo ra.
Đại tá Panic

@MattHickford Đó là một ví dụ về trường hợp kỳ lạ. Đoạn mã đó chuyển đến $ null nên Add-Contentkhông nhận được bất cứ thứ gì. Nếu Add-Contentkhông nhận được bất cứ điều gì tại sao nó phải tạo một tệp? Mặt khác, câu hỏi tương tự cũng có thể được đặt ra với Out-File.
Andy Arismendi

Các vấn đề khác biệt với tôi gci $folder | Out-File log.txt ; cat log.txtlàm việc trong khi gci $folder | Add-Content log.txt ; cat log.txtthổi lên
Đại Tá Panic

@MattHickford Có lẽ tôi muốn đảm bảo rằng tệp tồn tại trước khi cố gắng xử lý nó. Có lẽ là một thói quen tốt cho tất cả các ngôn ngữ.
Andy Arismendi

Một sự khác biệt khác là trong khi Set-Contentđang được sử dụng, tệp không có sẵn cho các ứng dụng khác.
Colonel Panic

10

Chà, tôi sẽ không đồng ý ... :)

  1. Out-File có -Append (-NoClober ở đó để tránh ghi đè) sẽ Add-Content. Nhưng đây không phải là cùng một con thú.
  2. lệnh | Add-Content sẽ sử dụng phương thức .ToString () trên đầu vào. Out-File sẽ sử dụng định dạng mặc định.

vì thế:

ls | Add-Content test.txt

ls | Out-File test.txt

sẽ cho bạn những kết quả hoàn toàn khác.

Và không, '>' không phải là bí danh, nó là toán tử chuyển hướng (giống như trong các trình bao khác). Và có hạn chế rất nghiêm trọng ... Nó sẽ cắt các dòng giống như cách chúng được hiển thị. Out-File có tham số -Width giúp bạn tránh điều này. Ngoài ra, với các toán tử chuyển hướng, bạn không thể quyết định mã hóa sẽ sử dụng.

HTH Bartek


3
Nó là một bí danh có nghĩa là >và Out-File là một thứ giống nhau. Họ gọi cùng một mã. Từ PowerShell in Action phiên bản thứ hai của 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
Điểm tốt về định dạng mặc định (Out-File) so với ToString (Add-Content)
Andy Arismendi

Quan điểm của tôi là: mặc dù cả hai đều giống nhau, nhưng bí danh có ý nghĩa trong PowerShell ... vì vậy tôi sẽ không sử dụng thuật ngữ này để mô tả mối quan hệ giữa chúng ...;) Bí danh thay thế lệnh, trong trường hợp này, nó sẽ tạo cú pháp : ls | > tệp.txt có thể. Rõ ràng, điều đó sẽ không hiệu quả ...
BartekB

1
Định dạng mặc định là cách đối tượng nhất định được trình bày trong bảng điều khiển. Hầu hết các lệnh ghép ngắn / đối tượng lõi đều có siêu dữ liệu định dạng thông báo cho PowerShell cách hiển thị chúng theo cách thân thiện với người dùng. Nói cách khác: kết quả đường dẫn của lệnh ra ngoài tệp có thể được sử dụng để lưu đầu ra của lệnh vào tệp mà không làm mất định dạng do PowerShell thực hiện.
BartekB

2
Vâng, tôi nghĩ rằng đó là một sự khác biệt quan trọng mà >không phải là tương đương chính xác cho out-file. Nếu bạn đặt $PSDefaultParameterValues["Out-File:Encoding"] = "UTF8", nó sẽ bị bỏ qua bởi >.
khôn ngoan

3

Set-Contenthỗ trợ -Encoding Byte, trong khi Out-Filekhông.

Vì vậy, khi bạn muốn ghi dữ liệu nhị phân hoặc kết quả của Text.Encoding#GetBytes()một tệp, bạn nên sử dụng Set-Content.


0

Out-file -append hoặc ">>" thực sự có thể kết hợp hai mã hóa trong cùng một tệp. Ngay cả khi tệp ban đầu là ascii hoặc ansi, nó sẽ thêm unicode theo mặc định vào cuối tệp. Nội dung bổ sung sẽ kiểm tra mã hóa và khớp với nó trước khi thêm vào. Btw, export-csv mặc định thành ascii (không dấu) và set-content / add-content thành ansi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.