PowerShell Set-Content и Out-File - в чем разница?

88

В PowerShell, в чем разница между Out-Fileи Set-Content? Или Add-Contentи Out-File -append?

Я обнаружил, что если я использую оба против одного и того же файла, текст полностью изменен .

(Второй второстепенный вопрос: >это псевдоним Out-File, верно?)

Полковник Паник
источник

Ответы:

95

Вот краткое изложение того, что я сделал после нескольких месяцев работы с PowerShell и некоторых научных экспериментов. Я не нашел ничего из этого в документации :(

[ Обновление: многое из этого теперь, кажется, лучше задокументировано.]

Блокировка чтения и записи

Во время Out-Fileработы другое приложение может читать файл журнала.

Во время Set-Contentработы другие приложения не могут прочитать файл журнала. Таким образом, никогда не используйтеSet-Content для регистрации длительно выполняющихся команд.

Кодирование

Out-Fileпо умолчанию сохраняет в кодировке Unicode( UTF-16LE) (хотя это можно указать), тогда как по Set-Contentумолчанию в PowerShell 3+ используется кодировка ASCII( US-ASCII) (это также может быть указано). В более ранних версиях PowerShell Set-Contentсодержимое записывалось в Defaultкодировке (ANSI).

Примечание редактора : PowerShell версии 5.1 по- прежнему использует Defaultкодировку, зависящую от языка и региональных параметров («ANSI»), несмотря на то, что утверждается в документации. Если бы ASCII был по умолчанию, символы, отличные от ASCII, например, üбыли бы преобразованы в буквальные ? , но это не так: 'ü' | Set-Content tmp.txt; (Get-Content tmp.txt) -eq '?'дает $False.

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

Это означает, что значения по умолчанию двух команд несовместимы, и их смешивание приведет к повреждению текста, поэтому всегда указывайте кодировку.

Форматирование

Как объяснил Бартек, Out-Fileсохраняет причудливое форматирование вывода, как видно в терминале. Итак, в папке с двумя файлами команда dir | out-file out.txtсоздает файл из 11 строк.

Тогда как Set-Contentспасает более простое представление. В этой папке с двумя файлами команда dir | set-content sc.txtсоздает файл с двумя строками. Чтобы эмулировать вывод в терминале:

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

Я считаю, что это форматирование имеет последствия для разрывов строк, но я пока не могу это описать.

Создание файла

Set-Contentне создает надежно пустой файл, если Out-Fileбы:

В пустой папке команда dir | out-file out.txtсоздает файл, а dir | set-content sc.txtне делает.

Переменная конвейера

Set-Contentберет имя файла из конвейера; позволяя вам установить некоторое фиксированное значение для содержимого нескольких файлов.

Out-Fileберет данные как из конвейера; обновление содержимого отдельного файла.

Параметры

Set-Content включает следующие дополнительные параметры:

  • Исключить
  • Фильтр
  • Включают
  • Пройти
  • Ручей
  • UseTransaction

Out-File включает следующие дополнительные параметры:

  • Добавить
  • NoClobber
  • Ширина

Для получения дополнительной информации об этих параметрах см. Справку; напр get-help out-file -parameter append.

Полковник Паник
источник
4
Set-Contentкодировка по умолчанию: переведена в (Get-Culture).Textinfo.ANSICodePage(Windows 8.1, Powershell 4.0, CurrentCulture cs-CZ, CurrentUICulture en-GB, ANSICodePage 1250, OEMCodePage 852, протестировано с использованием 'řž'строки с разными кодами в кодовых страницах выше).
JosefZ
Также обратите внимание, что Out-Fileв определенных ситуациях возникают проблемы с длинными линиями. Например: $x = [pscustomobject]@{A=('a' * 500); B=('b' * 500)}; $x | Out-File -Path myfile.txt.
Bacon Bits
17

Out-Fileимеет поведение перезаписи пути вывода, если не -NoClobberустановлен -Appendфлаг и / или . Add-Contentдобавит контент, если выходной путь уже существует по умолчанию (если может). Оба создадут файл, если он еще не существует.

Еще одно интересное отличие состоит в том, что Add-Contentпо умолчанию создается файл в кодировке ASCII, а по умолчанию - файл с Out-Fileпрямым порядком байтов в кодировке Unicode.

>является синтаксическим сахаром псевдонима для Out-File. Это Out-Fileс некоторыми предопределенными настройками параметров.

Энди Арисменди
источник
Спасибо, знание различий в кодировке полезно. Вы не совсем правы, если вы это сделаете, echo "" > $null | Add-Content abc.txtон не создаст файл abc.txt, а Out-File.
Полковник Паник,
@MattHickford Это довольно странный пример. Этот код передает $ null, поэтому Add-Contentничего не получает. Если Add-Contentничего не получает, зачем ему создавать файл? С другой стороны, тот же вопрос можно задать Out-File.
Энди Арисменди
Для меня разница имеет значение, gci $folder | Out-File log.txt ; cat log.txtработает тогда как gci $folder | Add-Content log.txt ; cat log.txtвзрывается
полковник Паник
@MattHickford Я бы, наверное, убедился, что файл существует, прежде чем пытаться его обработать. Наверное, хорошая привычка для всех языков.
Энди Арисменди
Другое отличие состоит в том, что пока Set-Contentфайл используется, он недоступен для других приложений.
Colonel Panic
10

Что ж, я бы не согласился ... :)

  1. Out-File имеет -Append (-NoClober существует, чтобы избежать перезаписи), который будет добавлять-Content. Но это не тот зверь.
  2. команда | Add-Content будет использовать метод .ToString () при вводе. Out-File будет использовать форматирование по умолчанию.

так:

ls | Add-Content test.txt

а также

ls | Out-File test.txt

даст вам совершенно другие результаты.

И нет, '>' не псевдоним, это оператор перенаправления (как и в других оболочках). И имеет очень серьезное ограничение ... Он будет обрезать линии так же, как они отображаются. В Out-File есть параметр -Width, который помогает избежать этого. Кроме того, с операторами перенаправления вы не можете решить, какую кодировку использовать.

HTH Bartek

BartekB
источник
3
Это псевдоним в том смысле, что >и Out-File - одно и то же. Они называют один и тот же код. Из PowerShell Брюса Пайетта в действии, второе издание (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.
Энди Арисменди,
1
Хорошее замечание о форматировании по умолчанию (Out-File) и ToString (Add-Content)
Энди Арисменди
Моя точка зрения заключалась в следующем: хотя оба обычно делают одно и то же, псевдоним имеет свое значение в PowerShell ... поэтому я бы не стал использовать этот термин для описания отношений между ними ...;) Псевдоним заменяет команду, в этом случае он должен создавать синтаксис : ls | > file.txt возможно. Очевидно, это не сработает ...
BartekB
1
Форматирование по умолчанию - это способ представления данного объекта в консоли. Большинство основных командлетов / типов объектов имеют метаданные форматирования, которые сообщают PowerShell, как их отображать в удобной для пользователя форме. Другими словами: передача результатов команды в Out-File может использоваться для сохранения вывода команды в файл без потери форматирования, выполняемого PowerShell.
BartekB 02
2
Да, я думаю, что это важное различие, >которое не является точным эквивалентом out-file. Если вы установите $PSDefaultParameterValues["Out-File:Encoding"] = "UTF8", он будет проигнорирован >.
wisbucky
3

Set-Contentподдерживает -Encoding Byte, пока Out-Fileнет.

Поэтому, когда вы хотите записать двоичные данные или результат Text.Encoding#GetBytes()в файл, вы должны использовать Set-Content.

САТО Юсуке
источник
0

Out-file -append или ">>" могут фактически смешивать две кодировки в одном файле. Даже если файл изначально имеет формат ascii или ansi, он по умолчанию добавит Unicode в его нижнюю часть. Add-content проверит кодировку и сопоставит ее перед добавлением. Кстати, для export-csv по умолчанию используется ascii (без диакритических знаков), а для установки содержимого / добавления содержимого в ansi.

js2010
источник