PowerShell Set-Content i Out-File - jaka jest różnica?

90

Jaka jest różnica między Out-Filei w PowerShell Set-Content? Albo Add-Contenti Out-File -append?

Odkryłem, że jeśli używam obu w tym samym pliku, tekst jest w pełni zmodyfikowany .

(Drugie drobne pytanie: >czy jest aliasem dla Out-File, prawda?)

Colonel Panic
źródło

Odpowiedzi:

97

Oto podsumowanie tego, co wydedukowałem po kilku miesiącach doświadczeń z PowerShell i kilku eksperymentach naukowych. Nigdy nie znalazłem tego w dokumentacji :(

[ Aktualizacja: większość z tego wydaje się być teraz lepiej udokumentowana.]

Odczyt i zapis blokowania

Podczas Out-Filedziałania inna aplikacja może odczytać plik dziennika.

Podczas Set-Contentdziałania inne aplikacje nie mogą odczytać pliku dziennika. Dlatego nigdy nie używajSet-Content do rejestrowania długo działających poleceń.

Kodowanie

Out-Filezapisuje w kodowaniu Unicode( UTF-16LE) domyślnie (chociaż można to określić), podczas gdy Set-Contentdomyślnie jest to ASCII( US-ASCII) w PowerShell 3+ (można to również określić). We wcześniejszych wersjach programu PowerShell Set-Contentzapisano zawartość w Defaultkodowaniu (ANSI).

Uwaga edytora : PowerShell od wersji 5.1 nadal domyślnie korzysta z Defaultkodowania specyficznego dla kultury („ANSI”), pomimo tego, co twierdzi dokumentacja. Gdyby wartość ASCII była domyślna, znaki inne niż ASCII, takie jak, üzostałyby przekonwertowane na literał ? , ale tak nie jest : 'ü' | Set-Content tmp.txt; (Get-Content tmp.txt) -eq '?'yields $False.

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

Oznacza to, że wartości domyślne dwóch poleceń są niekompatybilne, a mieszanie ich spowoduje uszkodzenie tekstu, dlatego zawsze określaj kodowanie.

Formatowanie

Jak wyjaśnił Bartek, Out-Filezapisuje fantazyjne formatowanie wyjścia, jak widać na terminalu. Tak więc w folderze z dwoma plikami polecenie dir | out-file out.txttworzy plik z 11 wierszami.

Natomiast Set-Contentzapisuje prostszą reprezentację. W tym folderze z dwoma plikami polecenie dir | set-content sc.txttworzy plik z dwoma wierszami. Aby emulować wyjście w terminalu:

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

Uważam, że to formatowanie ma wpływ na podziały wierszy, ale nie mogę tego jeszcze opisać.

Tworzenie plików

Set-Contentnie tworzy niezawodnie pustego pliku, gdy Out-File:

W pustym folderze polecenie dir | out-file out.txttworzy plik, a dir | set-content sc.txtnie.

Zmienna rurociągu

Set-Contentpobiera nazwę pliku z potoku; pozwalając na ustawienie pewnej stałej wartości wielu plików.

Out-Filepobiera dane z rurociągu; aktualizacja zawartości pojedynczego pliku.

Parametry

Set-Content zawiera następujące dodatkowe parametry:

  • Wykluczać
  • Filtr
  • Zawierać
  • Przejść przez
  • Strumień
  • UseTransaction

Out-File zawiera następujące dodatkowe parametry:

  • Dodać
  • NoClobber
  • Szerokość

Więcej informacji na temat tych parametrów można znaleźć w pomocy; np get-help out-file -parameter append.

Colonel Panic
źródło
4
Set-Contentdomyślne kodowanie: przetłumaczone na (Get-Culture).Textinfo.ANSICodePage(Windows 8.1, Powershell 4.0, CurrentCulture cs-CZ, CurrentUICulture en-GB, ANSICodePage 1250, OEMCodePage 852, testowane przy użyciu 'řž'ciągu z różnymi kodami na powyższych stronach kodowych).
JosefZ
Zauważ również, że Out-Filew niektórych sytuacjach ma problemy z długimi kolejkami. Na przykład: $x = [pscustomobject]@{A=('a' * 500); B=('b' * 500)}; $x | Out-File -Path myfile.txt.
Bacon Bits
17

Out-Filezachowuje się nadpisując ścieżkę wyjściową, chyba że ustawiono flagę -NoClobberi / lub -Append. Add-Contentdoda zawartość, jeśli ścieżka wyjściowa już istnieje domyślnie (jeśli może). Obie utworzą plik, jeśli jeszcze nie istnieje.

Inną interesującą różnicą jest to, że Add-Contentdomyślnie Out-Fileutworzy plik zakodowany w ASCII i domyślnie utworzy plik z kodowaniem little endian Unicode.

>to alias syntactic sugar for Out-File. Jest Out-Filez kilkoma wstępnie zdefiniowanymi ustawieniami parametrów.

Andy Arismendi
źródło
Dzięki, znajomość różnic w kodowaniu jest przydatna. Nie masz racji, jeśli to zrobisz echo "" > $null | Add-Content abc.txt, nie utworzysz pliku abc.txt, podczas gdy Out-File to zrobi.
Panika pułkownika
@MattHickford To trochę dziwny przykład. Ten kod przekierowuje do $ null, więc Add-Contentnic nie otrzymuje. Jeśli Add-Contentnie otrzyma niczego, dlaczego miałby utworzyć plik? Z drugiej strony to samo pytanie można by zadać Out-File.
Andy Arismendi
Sprawy różnicy mnie gci $folder | Out-File log.txt ; cat log.txtdziała natomiast gci $folder | Add-Content log.txt ; cat log.txtwysadza
pułkownika Panic
@MattHickford Prawdopodobnie upewniłbym się, że plik istnieje, zanim spróbuję go przetworzyć. Prawdopodobnie dobry nawyk dla wszystkich języków.
Andy Arismendi
Inną różnicą jest to, że podczas Set-Contentużywania plik jest niedostępny dla innych aplikacji.
Panika pułkownika
10

Cóż, nie zgodziłbym się ... :)

  1. Out-File ma -Append (-NoClober jest po to, aby uniknąć nadpisania), które doda zawartość. Ale to nie jest ta sama bestia.
  2. polecenie | Add-Content użyje metody .ToString () na wejściu. Out-File użyje domyślnego formatowania.

więc:

ls | Add-Content test.txt

i

ls | Out-File test.txt

da zupełnie inne rezultaty.

I nie, „>” nie jest aliasem, jest operatorem przekierowania (tak samo jak w innych powłokach). I ma bardzo poważne ograniczenia ... Będzie wycinać linie w taki sam sposób, w jaki są wyświetlane. Out-File ma parametr -Width, który pomaga tego uniknąć. Ponadto w przypadku operatorów przekierowania nie możesz zdecydować, jakiego kodowania użyć.

HTH Bartek

BartekB
źródło
3
Jest to alias w tym sensie, że >i Out-File to to samo. Nazywają ten sam kod. Z programu PowerShell w akcji Bruce'a Payette'a Wydanie drugie (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
Dobra uwaga na temat domyślnego formatowania (Out-File) vs ToString (Add-Content)
Andy Arismendi
Chodziło mi o to: chociaż oba generalnie robią to samo, alias ma swoje znaczenie w PowerShell ... więc nie użyłbym tego terminu do opisania relacji między nimi ...;) Alias ​​zastępuje polecenie, w tym przypadku powinien tworzyć składnię : ls | > plik.txt możliwy. Oczywiście to nie zadziała ...
BartekB
1
Domyślne formatowanie to sposób prezentacji danego obiektu w konsoli. Większość podstawowych poleceń cmdlet / typów obiektów ma metadane formatowania, które informują program PowerShell, jak wyświetlać je w sposób przyjazny dla użytkownika. Innymi słowy: wyniki polecenia potokowaniem do pliku wyjściowego mogą być użyte do zapisania wyniku polecenia do pliku, bez utraty formatowania wykonanego przez PowerShell.
BartekB
2
Tak, myślę, że to ważne rozróżnienie, które >nie jest dokładnym odpowiednikiem out-file. Jeśli ustawisz $PSDefaultParameterValues["Out-File:Encoding"] = "UTF8", zostanie zignorowany przez >.
wisbucky
3

Set-Contentobsługuje -Encoding Byte, a Out-Filenie.

Więc jeśli chcesz zapisać dane binarne lub wynik Text.Encoding#GetBytes()do pliku, powinieneś użyć Set-Content.

SATO Yusuke
źródło
0

Out-file -append lub „>>” może w rzeczywistości mieszać dwa kodowania w tym samym pliku. Nawet jeśli pierwotnie plik jest ascii lub ansi, domyślnie doda unicode na dole. Add-content sprawdzi kodowanie i dopasuje je przed dołączeniem. Btw, export-csv domyślnie ustawia ascii (bez akcentów), a set-content / add-content na ansi.

js2010
źródło
0

Chciałem dodać różnicę w kodowaniu:

Windows z PowerShell 5.1:

  • Plik wyjściowy - domyślne kodowanie to utf-16le
  • Set-Content - Domyślne kodowanie to us-ascii

Linux z PowerShell 7.1:

  • Plik wyjściowy - domyślne kodowanie to us-ascii
  • Set-Content - Domyślne kodowanie to us-ascii
JagWireZ
źródło