Set-Content e Out-File do PowerShell - qual é a diferença?

87

No PowerShell, qual é a diferença entre Out-Filee Set-Content? Ou Add-Contente Out-File -append?

Descobri que, se usar ambos no mesmo arquivo, o texto será totalmente modificado .

(Uma segunda pergunta secundária: >é um alias para Out-File, certo?)

Coronel Panic
fonte

Respostas:

95

Aqui está um resumo do que deduzi, após alguns meses de experiência com o PowerShell e alguns experimentos científicos. Nunca encontrei nada disso na documentação :(

[ Atualização: muito disso agora parece estar melhor documentado.]

Bloqueio de leitura e gravação

Enquanto Out-Fileestá em execução, outro aplicativo pode ler o arquivo de log.

Enquanto Set-Contentestiver em execução, outros aplicativos não podem ler o arquivo de log. Portanto, nunca useSet-Content para registrar comandos de longa duração.

Codificação

Out-Filesalva na codificação Unicode( UTF-16LE) por padrão (embora isso possa ser especificado), enquanto o Set-Contentpadrão é ASCII( US-ASCII) no PowerShell 3+ (isso também pode ser especificado). Em versões anteriores do PowerShell, Set-Contentescrevia conteúdo na Defaultcodificação (ANSI).

Nota do editor : o PowerShell a partir da versão 5.1 ainda é padronizado para a Defaultcodificação específica da cultura ("ANSI"), apesar do que a documentação afirma. Se ASCII fosse o padrão, caracteres não ASCII, como üseriam convertidos em literais ? , mas esse não é o caso: 'ü' | Set-Content tmp.txt; (Get-Content tmp.txt) -eq '?'rendimentos $False.

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

Isso significa que os padrões de dois comandos são incompatíveis e misturá-los irá corromper o texto, portanto, sempre especifique uma codificação.

Formatação

Como Bartek explicou, Out-Filesalva a formatação extravagante da saída, conforme visto no terminal. Portanto, em uma pasta com dois arquivos, o comando dir | out-file out.txtcria um arquivo com 11 linhas.

Considerando que Set-Contentsalva uma representação mais simples. Nessa pasta com dois arquivos, o comando dir | set-content sc.txtcria um arquivo com duas linhas. Para emular a saída no terminal:

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

Acredito que essa formatação tenha consequências para quebras de linha, mas ainda não consigo descrevê-la.

Criação de arquivo

Set-Contentnão cria de maneira confiável um arquivo vazio quando Out-File:

Em uma pasta vazia, o comando dir | out-file out.txtcria um arquivo, enquanto dir | set-content sc.txtnão.

Variável de pipeline

Set-Contentpega o nome do arquivo do pipeline; permitindo que você defina um número de conteúdo de arquivos para algum valor fixo.

Out-Filepega os dados a partir do pipeline; atualizar o conteúdo de um único arquivo.

Parâmetros

Set-Content inclui os seguintes parâmetros adicionais:

  • Excluir
  • Filtro
  • Incluir
  • Passar através
  • Corrente
  • UseTransaction

Out-File inclui os seguintes parâmetros adicionais:

  • Acrescentar
  • NoClobber
  • Largura

Para obter mais informações sobre o que são esses parâmetros, consulte a ajuda; por exemplo get-help out-file -parameter append.

Coronel Panic
fonte
4
Set-Contentcodificação padrão: traduzido para (Get-Culture).Textinfo.ANSICodePage(Windows 8.1, Powershell 4.0, CurrentCulture cs-CZ, CurrentUICulture en-GB, ANSICodePage 1250, OEMCodePage 852, testado usando 'řž'string com códigos diferentes nas páginas de código acima).
JosefZ
Observe também que Out-Filetem problemas com filas longas em certas situações. Por exemplo: $x = [pscustomobject]@{A=('a' * 500); B=('b' * 500)}; $x | Out-File -Path myfile.txt.
Bacon Bits de
17

Out-Filetem o comportamento de sobrescrever o caminho de saída, a menos que o -NoClobbere / ou o -Appendsinalizador seja definido. Add-Contentacrescentará conteúdo se o caminho de saída já existir por padrão (se puder). Ambos criarão o arquivo, se ainda não houver um.

Outra diferença interessante é que Add-Contentcriará um arquivo codificado em ASCII por padrão e Out-Filecriará um pequeno arquivo codificado em unicode endian por padrão.

>é um alias de açúcar sintático para Out-File. É Out-Filecom algumas configurações de parâmetros predefinidos.

Andy Arismendi
fonte
Obrigado, saber as diferenças de codificação é útil. Você não está certo, se você fizer echo "" > $null | Add-Content abc.txtisso não criará o arquivo abc.txt, mas Out-File faria.
Coronel Panic de
@MattHickford Esse é um exemplo estranho de caso extremo. Esse código direciona para $ null, portanto Add-Content, não recebe nada. Se Add-Contentnão recebe nada, por que deveria criar um arquivo? Por outro lado, a mesma pergunta poderia ser feita para Out-File.
Andy Arismendi
A diferença importa para mim gci $folder | Out-File log.txt ; cat log.txtfunciona enquanto gci $folder | Add-Content log.txt ; cat log.txtexplode
Coronel Panic
@MattHickford Provavelmente, verificaria se o arquivo existe antes de tentar processá-lo. Provavelmente um bom hábito para todos os idiomas.
Andy Arismendi
Outra diferença é que, enquanto Set-Contentestá sendo usado, o arquivo fica indisponível para outros aplicativos.
Coronel Panic
10

Bem, eu discordo ... :)

  1. Out-File tem -Append (-NoClober está lá para evitar sobrescrever) que irá adicionar conteúdo. Mas esta não é a mesma besta.
  2. comando | Add-Content usará o método .ToString () na entrada. Out-File usará a formatação padrão.

tão:

ls | Add-Content test.txt

e

ls | Out-File test.txt

lhe dará resultados totalmente diferentes.

E não, '>' não é um alias, é um operador de redirecionamento (o mesmo que em outros shells). E tem limitação muito séria ... Vai cortar as linhas da mesma forma que são exibidas. Out-File tem o parâmetro -Width que ajuda a evitar isso. Além disso, com os operadores de redirecionamento, você não pode decidir qual codificação usar.

HTH Bartek

BartekB
fonte
3
É um apelido no sentido de que >e Out-File são a mesma coisa. Eles chamam o mesmo código. Do PowerShell em ação, segunda edição 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
Bom ponto sobre a formatação padrão (Out-File) vs ToString (Add-Content)
Andy Arismendi
Meu ponto era: embora ambos façam geralmente o mesmo, alias tem seu significado no PowerShell ... então eu não usaria este termo para descrever a relação entre eles também ...;) Alias ​​substitui o comando, neste caso ele deve fazer a sintaxe : ls | > arquivo.txt possível. Obviamente, isso não vai funcionar ...
BartekB
1
A formatação padrão é a forma como determinado objeto é apresentado no console. A maioria dos cmdlets / tipos de objeto principais tem metadados de formatação que informam ao PowerShell como exibi-los de maneira amigável. Em outras palavras: canalizar os resultados do comando para Out-File pode ser usado para salvar a saída do comando para o arquivo, sem perder a formatação feita pelo PowerShell.
BartekB
2
Sim, acho que é uma distinção importante para a qual >não é o equivalente exato out-file. Se você definir $PSDefaultParameterValues["Out-File:Encoding"] = "UTF8", ele será ignorado por >.
wisbucky
3

Set-Contentsuporta -Encoding Byte, enquanto Out-Filenão.

Portanto, quando quiser gravar dados binários ou resultados Text.Encoding#GetBytes()em um arquivo, você deve usar Set-Content.

SATO Yusuke
fonte
0

Out-file -append ou ">>" pode, na verdade, misturar duas codificações no mesmo arquivo. Mesmo se o arquivo for originalmente ascii ou ansi, ele adicionará unicode por padrão ao final dele. Add-content irá verificar a codificação e combiná-la antes de anexar. A propósito, export-csv padroniza para ascii (sem acentos), e set-content / add-content para ansi.

js2010
fonte