Сравните два текстовых файла и запишите различия в текстовый файл
Я хочу сравнить 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
перед записью данных в файл.