Сравните два текстовых файла и запишите различия в текстовый файл

Я хочу сравнить 2 текстовых файла и вывести разницу в другом текстовом файле.

$Location = "c:\temp\z.txt"
compare-object (get-content c:\temp\hostname_old.txt) (get-content c:\temp\hostname_new.txt) | format-list | Out-File $Location

hostname_old.txt

server02
server05
server04
server06
server01

hostname_new.txt

server04
server01
server02

Результаты

InputObject   : server05
SideIndicator : <=

InputObject   : server06
SideIndicator : <=

Это то, что я хочу: (избавиться от InputObject и SideIndicator)

server05
server06

Примечание. Предметом этого вопроса является связанная с этим проблема, когда в одном входном файле есть повторяющиеся записи.

3 ответа

Просто используйте параметр -PassThru:

compare-object (get-content c:\temp\hostname_old.txt) (get-content c:\temp\hostname_new.txt) -PassThru | Out-File $Location

делает именно то, что вы хотите.

Обновление: полезный ответ Palle Due предлагает лучшее решение.
Этот ответ может по-прежнему представлять интерес для сопоставления перечисления элементов с использованием конвейера, обсуждения форматирования вывода и сопоставления Out-File с Set-Content,


В PSv3+ вы можете просто использовать перечисление членов для извлечения .InputObject ценности:

PS> (Compare-Object (Get-Content old.txt) (Get-Content new.txt)).InputObject
server05
server06

Замечания:

  • Перечисление членов удобно и быстро, но за счет потребления памяти, что может быть проблемой для очень больших коллекций (не здесь). Выход из Compare-Object должны быть собраны в памяти в целом в массиве ([object[]]) и, аналогично, .InputObject Значения свойств возвращаются в виде массива.

  • Для более медленной, но дружественной памяти потоковой передачи (обработка по одному) используйте конвейер с Select-Object -ExpandProperty, как в эффективном решении TobyU.

Повторное сохранение в файл: piping to Out-File $location (или, более кратко, используя перенаправление вывода: > $location) достаточно - не нужно Format-List,

В общем, обратите внимание, что цель Format-* Командлеты предназначены для вывода на экран, а не для программной обработки и сохранения.

Это сказало, Out-File / > (эффективно) использует Format-* Командлеты за кулисами создают строковое представление объектов ввода, подобно выводу на консоль по умолчанию, поэтому эта команда не подходит для сохранения произвольных объектов ввода.

Использование Out-File / > со строками безопасно, однако, потому что они выводятся как есть. Напротив, четные числа проблематичны, если они имеют десятичные разряды, потому что они строковые с десятичным разделителем текущей культуры (например, , скорее, чем . в некоторых культурах).

Если ваши входные объекты являются строками, вы можете использовать Set-Content , который быстрее чем Out-File / >, но предостережение в том, что в Windows PowerShell кодировка символов, используемая по умолчанию, отличается: Out-File / > по умолчанию создает файлы UTF-16LE, тогда как Set-Content использует кодовую страницу "ANSI" устаревшей языковой системы (как правило, однобайтовую 8-битную кодировку, такую ​​как Windows-1252).
Напротив, в PowerShell Core оба командлета производят UTF-8 без спецификации.

Обратите внимание, что Set-Content, В отличие от Out-File, преобразует не строковые объекты, просто вызывая .ToString() метод на них.

Я думаю, вы ищете Select-Object -ExpandProperty InputObject

compare-object (get-content c:\temp\hostname_old.txt) (get-content c:\temp\hostname_new.txt) | Select-Object -ExpandProperty InputObject | Out-File $Location

Обратите внимание, что вы не можете использовать format-list в Pipeline перед записью данных в файл.

Другие вопросы по тегам