PowerShell Set-Content et Out-File - quelle est la différence?

87

Dans PowerShell, quelle est la différence entre Out-Fileet Set-Content? Ou Add-Contentet Out-File -append?

J'ai trouvé que si j'utilise les deux contre le même fichier, le texte est entièrement mojibaked .

(Une deuxième question mineure: >est un alias pour Out-File, non?)

Colonel Panic
la source

Réponses:

95

Voici un résumé de ce que j'ai déduit, après quelques mois d'expérience avec PowerShell, et quelques expériences scientifiques. Je n'ai jamais rien trouvé de cela dans la documentation :(

[ Mise à jour: une grande partie de cela semble maintenant être mieux documentée.]

Verrouillage en lecture et en écriture

Pendant l' Out-Fileexécution, une autre application peut lire le fichier journal.

Pendant l' Set-Contentexécution, les autres applications ne peuvent pas lire le fichier journal. N'utilisez donc jamaisSet-Content pour enregistrer des commandes de longue durée.

Codage

Out-Fileenregistre dans le codage Unicode( UTF-16LE) par défaut (bien que cela puisse être spécifié), alors que la valeur par Set-Contentdéfaut est ASCII( US-ASCII) dans PowerShell 3+ (cela peut également être spécifié). Dans les versions antérieures de PowerShell, Set-Contentrédigeait le contenu dans le Defaultcodage (ANSI).

Note de l'éditeur : PowerShell à partir de la version 5.1 utilise toujours le Defaultcodage spécifique à la culture ("ANSI"), malgré ce que la documentation affirme. Si ASCII était la valeur par défaut, les caractères non ASCII tels que üseraient convertis en littéral ? , mais ce n'est pas le cas: 'ü' | Set-Content tmp.txt; (Get-Content tmp.txt) -eq '?'renvoie $False.

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

Cela signifie que les valeurs par défaut de deux commandes sont incompatibles et que les mélanger endommagera le texte, alors spécifiez toujours un encodage.

Mise en page

Comme Bartek l'a expliqué, Out-Fileenregistre le formatage sophistiqué de la sortie, comme on le voit dans le terminal. Ainsi, dans un dossier avec deux fichiers, la commande dir | out-file out.txtcrée un fichier avec 11 lignes.

Alors que Set-Contentenregistre une représentation plus simple. Dans ce dossier avec deux fichiers, la commande dir | set-content sc.txtcrée un fichier avec deux lignes. Pour émuler la sortie dans le terminal:

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

Je pense que ce formatage a une conséquence sur les sauts de ligne, mais je ne peux pas encore le décrire.

Création de fichier

Set-Contentne crée pas de manière fiable un fichier vide quand Out-File:

Dans un dossier vide, la commande dir | out-file out.txtcrée un fichier, mais dir | set-content sc.txtpas.

Variable de pipeline

Set-Contentprend le nom de fichier du pipeline; vous permettant de définir le contenu d'un certain nombre de fichiers sur une valeur fixe.

Out-Fileprend les données à partir du pipeline; mettre à jour le contenu d'un seul fichier.

Paramètres

Set-Content comprend les paramètres supplémentaires suivants:

  • Exclure
  • Filtre
  • Comprendre
  • Passer à travers
  • Courant
  • UtiliserTransaction

Out-File comprend les paramètres supplémentaires suivants:

  • Ajouter
  • NoClobber
  • Largeur

Pour plus d'informations sur ces paramètres, reportez-vous à l'aide; par exemple get-help out-file -parameter append.

Colonel Panic
la source
4
Set-Contentencodage par défaut: traduit en (Get-Culture).Textinfo.ANSICodePage(Windows 8.1, Powershell 4.0, CurrentCulture cs-CZ, CurrentUICulture en-GB, ANSICodePage 1250, OEMCodePage 852, testé en utilisant une 'řž'chaîne avec différents codes dans les pages de codes ci-dessus).
JosefZ
Notez également que cela Out-Filea des problèmes avec les longues lignes dans certaines situations. Par exemple: $x = [pscustomobject]@{A=('a' * 500); B=('b' * 500)}; $x | Out-File -Path myfile.txt.
Bacon Bits
17

Out-Filea le comportement d'écraser le chemin de sortie à moins que -NoClobberl' -Appendindicateur et / ou ne soit défini. Add-Contentajoutera du contenu si le chemin de sortie existe déjà par défaut (si c'est possible). Les deux créeront le fichier s'il n'en existe pas déjà un.

Une autre différence intéressante est que Add-Contentcréera un fichier encodé ASCII par défaut et Out-Filecréera un petit fichier encodé unicode endian par défaut.

>est un sucre syntaxique alias pour Out-File. C'est Out-Fileavec quelques réglages de paramètres prédéfinis.

Andy Arismendi
la source
Merci, connaître les différences d'encodage est utile. Vous n'avez pas tout à fait raison, si vous le faites, echo "" > $null | Add-Content abc.txtcela ne crée pas le fichier abc.txt, contrairement à Out-File.
Colonel Panic
@MattHickford C'est un exemple de cas étrange. Ce code redirige vers $ null et Add-Contentne reçoit donc rien. S'il Add-Contentne reçoit rien, pourquoi devrait-il créer un fichier? En revanche, la même question pourrait être posée à Out-File.
Andy Arismendi
La différence compte pour moi gci $folder | Out-File log.txt ; cat log.txtfonctionne alors que ça gci $folder | Add-Content log.txt ; cat log.txtexplose
Colonel Panic
@MattHickford Je m'assurerais probablement que le fichier existe avant d'essayer de le traiter. Probablement une bonne habitude pour toutes les langues.
Andy Arismendi
Une autre différence est que pendant Set-Contentson utilisation, le fichier n'est pas disponible pour les autres applications.
Colonel Panic
10

Eh bien, je ne serais pas d'accord ... :)

  1. Out-File a -Append (-NoClober est là pour éviter l'écrasement) qui ajoutera du contenu. Mais ce n'est pas la même bête.
  2. commande | Add-Content utilisera la méthode .ToString () en entrée. Out-File utilisera le formatage par défaut.

donc:

ls | Add-Content test.txt

et

ls | Out-File test.txt

vous donnera des résultats totalement différents.

Et non, '>' n'est pas un alias, c'est un opérateur de redirection (comme dans les autres shells). Et a une limitation très sérieuse ... Il coupera les lignes de la même manière qu'elles sont affichées. Out-File a le paramètre -Width qui vous aide à éviter cela. De plus, avec les opérateurs de redirection, vous ne pouvez pas décider du codage à utiliser.

HTH Bartek

BartekB
la source
3
C'est un alias dans le sens où >Out-File est la même chose. Ils appellent le même code. Tiré de PowerShell in Action Second Edition de 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
Bon point sur le formatage par défaut (Out-File) vs ToString (Add-Content)
Andy Arismendi
Mon point était: même si les deux font généralement la même chose, alias a sa signification dans PowerShell ... donc je n'utiliserais pas ce terme pour décrire la relation entre ceux-ci aussi ..;) Alias ​​remplace la commande, dans ce cas, il devrait créer une syntaxe : ls | > file.txt possible. Évidemment, cela ne fonctionnera pas ...
BartekB
1
Le formatage par défaut est la façon dont l'objet donné est présenté dans la console. La plupart des applets de commande / types d'objet principaux ont des métadonnées de mise en forme qui indiquent à PowerShell comment les afficher de manière conviviale. En d'autres termes: le transfert des résultats de la commande vers Out-File peut être utilisé pour enregistrer la sortie de la commande dans le fichier, sans perdre le formatage effectué par PowerShell.
BartekB
2
Oui, je pense que c'est une distinction importante qui >n'est pas exactement l'équivalent out-file. Si vous définissez $PSDefaultParameterValues["Out-File:Encoding"] = "UTF8", il sera ignoré par >.
wisbucky
3

Set-Contentprend en charge -Encoding Byte, tandis Out-Fileque non.

Ainsi, lorsque vous souhaitez écrire des données binaires ou des résultats Text.Encoding#GetBytes()dans un fichier, vous devez utiliser Set-Content.

SATO Yusuke
la source
0

Out-file -append ou ">>" peut en fait mélanger deux encodages dans le même fichier. Même si le fichier est à l'origine ascii ou ansi, il ajoutera unicode par défaut au bas de celui-ci. Add-content vérifiera l'encodage et le fera correspondre avant l'ajout. Btw, export-csv prend par défaut ascii (sans accents) et set-content / add-content sur ansi.

js2010
la source