PowerShell Set-Content e Out-File: qual è la differenza?


90

In PowerShell, qual è la differenza tra Out-Filee Set-Content? Oppure Add-Contente Out-File -append?

Ho scoperto che se utilizzo entrambi sullo stesso file, il testo è completamente mojibaked .

(Una seconda domanda minore: >è un alias per Out-File, giusto?)

Risposte:


96

Ecco un riepilogo di ciò che ho dedotto, dopo alcuni mesi di esperienza con PowerShell, e alcune sperimentazioni scientifiche. Non ho mai trovato niente di tutto questo nella documentazione :(

[ Aggiornamento: gran parte di questo ora sembra essere meglio documentato.]

Lettura e scrittura del blocco

Mentre Out-Fileè in esecuzione, un'altra applicazione può leggere il file di registro.

Durante l' Set-Contentesecuzione, altre applicazioni non possono leggere il file di registro. Quindi non usare maiSet-Content per registrare comandi a esecuzione prolungata.

Codifica

Out-Filesalva nella codifica Unicode( UTF-16LE) per impostazione predefinita (sebbene questo possa essere specificato), mentre il Set-Contentvalore predefinito è ASCII( US-ASCII) in PowerShell 3+ (anche questo può essere specificato). Nelle versioni precedenti di PowerShell, Set-Contentscriveva il contenuto nella Defaultcodifica (ANSI).

Nota del redattore : PowerShell a partire dalla versione 5.1 utilizza ancora la Defaultcodifica specifica delle impostazioni cultura ("ANSI"), nonostante ciò che afferma la documentazione. Se ASCII fosse l'impostazione predefinita, i caratteri non ASCII come üverrebbero convertiti in letterali ? , ma non è così: 'ü' | Set-Content tmp.txt; (Get-Content tmp.txt) -eq '?'produce $False.

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

Ciò significa che i valori predefiniti di due comandi sono incompatibili e mescolarli danneggerà il testo, quindi specifica sempre una codifica.

Formattazione

Come ha spiegato Bartek, Out-Filesalva la formattazione di fantasia dell'output, come si vede nel terminale. Quindi in una cartella con due file, il comando dir | out-file out.txtcrea un file con 11 righe.

Mentre Set-Contentsalva una rappresentazione più semplice. In quella cartella con due file, il comando dir | set-content sc.txtcrea un file con due righe. Per emulare l'output nel terminale:

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

Credo che questa formattazione abbia una conseguenza per le interruzioni di riga, ma non posso ancora descriverla.

Creazione di file

Set-Contentnon crea in modo affidabile un file vuoto quando Out-File:

In una cartella vuota, il comando dir | out-file out.txtcrea un file, mentre dir | set-content sc.txtnon lo fa.

Variabile pipeline

Set-Contentprende il nome del file dalla pipeline; consentendo di impostare un numero di contenuti di file su un valore fisso.

Out-Fileprende i dati come dalla pipeline; aggiornare il contenuto di un singolo file.

Parametri

Set-Content include i seguenti parametri aggiuntivi:

  • Escludere
  • Filtro
  • Includere
  • Passare attraverso
  • Stream
  • UseTransaction

Out-File include i seguenti parametri aggiuntivi:

  • Aggiungere
  • NoClobber
  • Larghezza

Per ulteriori informazioni su quali sono questi parametri, fare riferimento alla guida; es get-help out-file -parameter append.


4
Set-Contentcodifica predefinita: tradotta in (Get-Culture).Textinfo.ANSICodePage(Windows 8.1, Powershell 4.0, CurrentCulture cs-CZ, CurrentUICulture en-GB, ANSICodePage 1250, OEMCodePage 852, testato utilizzando 'řž'stringhe con codici diversi nelle tabelle codici precedenti).
JosefZ

Si noti inoltre che Out-Fileha problemi con le lunghe code in determinate situazioni. Ad esempio: $x = [pscustomobject]@{A=('a' * 500); B=('b' * 500)}; $x | Out-File -Path myfile.txt.
Bacon Bits

17

Out-Fileha il comportamento di sovrascrivere il percorso di output a meno che non sia impostato -NoClobberil -Appendflag e / o . Add-Contentaggiungerà contenuto se il percorso di output esiste già per impostazione predefinita (se possibile). Entrambi creeranno il file se non ne esiste già uno.

Un'altra differenza interessante è che Add-Contentcreerà un file con codifica ASCII per impostazione predefinita e Out-Filecreerà un piccolo file con codifica unicode endian per impostazione predefinita.

>è uno zucchero sintattico alias per Out-File. È Out-Filecon alcune impostazioni dei parametri predefinite.


Grazie, conoscere le differenze di codifica è utile. Tu non sei perfettamente ragione, se lo si fa echo "" > $null | Add-Content abc.txtche non crea il file abc.txt, mentre Out-File avrebbe fatto.
Colonel Panic

@ MattHickford Questo è un po 'uno strano esempio di caso limite. Quel codice trasmette a $ null quindi Add-Contentnon riceve nulla. Se Add-Contentnon riceve nulla, perché dovrebbe creare un file? D'altra parte la stessa domanda potrebbe essere posta a Out-File.
Andy Arismendi

La differenza per me è importante gci $folder | Out-File log.txt ; cat log.txtmentre gci $folder | Add-Content log.txt ; cat log.txtesplode
Colonel Panic

@ MattHickford Probabilmente mi assicurerei che il file esista prima di provare a elaborarlo. Probabilmente una buona abitudine per tutte le lingue.
Andy Arismendi

Un'altra differenza è che mentre Set-Contentviene utilizzato, il file non è disponibile per altre applicazioni.
Colonel Panic

10

Beh, non sarei d'accordo ... :)

  1. Out-File ha -Append (-NoClober è lì per evitare la sovrascrittura) che aggiungerà contenuto. Ma questa non è la stessa bestia.
  2. comando | Add-Content utilizzerà il metodo .ToString () sull'input. Out-File utilizzerà la formattazione predefinita.

così:

ls | Add-Content test.txt

e

ls | Out-File test.txt

ti darà risultati completamente diversi.

E no, ">" non è un alias, è un operatore di reindirizzamento (come in altre shell). E ha una limitazione molto seria ... Taglia le linee nello stesso modo in cui vengono visualizzate. Out-File ha il parametro -Width che ti aiuta a evitarlo. Inoltre, con gli operatori di reindirizzamento non puoi decidere quale codifica utilizzare.

HTH Bartek


3
È un alias nel senso che >e Out-File sono la stessa cosa. Chiamano lo stesso codice. Dal PowerShell in Action di Bruce Payette, seconda edizione (Posizioni Kindle 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
Buon punto sulla formattazione predefinita (Out-File) e ToString (Add-Content)
Andy Arismendi

Il mio punto era: anche se entrambi fanno generalmente lo stesso, alias ha il suo significato in PowerShell ... quindi non userei questo termine per descrivere anche la relazione tra quelli ..;) Alias ​​sostituisce il comando, in questo caso dovrebbe fare la sintassi : ls | > file.txt possibile. Ovviamente, non funzionerà ...
BartekB

1
La formattazione predefinita è il modo in cui un oggetto viene presentato nella console. La maggior parte dei cmdlet / tipi di oggetto principali ha metadati di formattazione che informano PowerShell su come visualizzarli in modo intuitivo. In altre parole: il reindirizzamento dei risultati del comando a Out-File può essere utilizzato per salvare l'output del comando nel file, senza perdere la formattazione eseguita da PowerShell.
BartekB

2
Sì, penso che sia una distinzione importante che >non è l'esatto equivalente per out-file. Se imposti $PSDefaultParameterValues["Out-File:Encoding"] = "UTF8", verrà ignorato da >.
wisbucky

3

Set-Contentsupporta -Encoding Byte, mentre Out-Filenon lo fa.

Quindi, quando vuoi scrivere dati binari o il risultato di Text.Encoding#GetBytes()un file, dovresti usare Set-Content.


0

Out-file -append o ">>" possono effettivamente mischiare due codifiche nello stesso file. Anche se il file è originariamente ASCII o ANSI, aggiungerà Unicode per impostazione predefinita in fondo. Il contenuto aggiuntivo verificherà la codifica e la farà corrispondere prima di aggiungerla. A proposito, export-csv è predefinito su ascii (senza accenti) e set-content / add-content su ansi.


0

Volevo aggiungere la differenza sulla codifica:

Windows con PowerShell 5.1:

  • Out-File: la codifica predefinita è utf-16le
  • Set-Content: la codifica predefinita è us-ascii

Linux con PowerShell 7.1:

  • Out-File: la codifica predefinita è us-ascii
  • Set-Content: la codifica predefinita è us-ascii
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.