Глава 6. Конвейер: соединение команд

В Главе 4 вы изучали что запуск команд в PowerShell в точности такой же как и запуск команд в любой иной оболочке: вы набираете название командлета, снабжаете его параметрами и нажимаете Enter. То что выделяет PowerShell, так это не сам способ запуска команд, а тот способ, коим он допускает соединение множества команд друг с другом мощной последовательностью в одну строку.

Соединение одной команды с другой: меньше работы для вас

PowerShell соединяет команды друг с другом применяя конвейер (pipeline). Такой конвейер обеспечивает способ пропуска, или передачи, для одной команды её вывода в другую команду, позволяя этой второй команде иметь нечто для работы. Это можно обнаружит при помощи вертикальной черты | между двумя командлетами.

 

Рисунок 6-1


Отображение передачи | в команде

Вы уже наблюдали это в действии в таких командах как Dir | more. Вы передаёте получаемый от команды Dir вывод в команду more; эта команда more получает такой список каталога и отображает его по странице за раз. PowerShell принимает такое понятие конвейера и расширяет его с большим эффектом.

Поначалу применение конвейера в PowerShell может показаться похожим на то, как работают оболочки UNIX и Linux. Однако не дайте себя обмануть. Как вы поймёте из следующих нескольких глав, реализация конвейера PowerShell намного богаче и современнее.

Экспорт в файл

PowerShell предоставляет несколько мощных способов экспорта данных в полезные форматы, такие как TXT, CSV, JSON и XML (Extensible Markup Language). В своём рабочем процессе вам может потребоваться экспорт данных из Azure Active Directory или из облачного хранилища. В данной главе мы пройдёмся по такому процессу передачи данных. Мы начнём с получения данных из некой простой встроенной команды для упрощения своего процесса, однако само понятие остаётся тем же самым.

Давайте начнём с запуска нескольких простых команд. Затем мы изучим как соединять их вместе. Вот несколько команд, которыми мы можем воспользоваться:

  • Get-Process (или gps)

  • Get-Command (или gcm)

  • Get-History -count 10 (или h)

Мы будем придерживаться этих команд, поскольку они лёгкие и простые. Мы снабдили вас псевдонимами Get-Process и Get-Commandв скобках. Для Get-History мы определили параметр -count со значением 10, а потому он выдаст лишь последние 10 записей истории.

[Совет]Попробуйте прямо сейчас

Проследуйте вперёд и выберите ту команду, с которой вы хотите работать. Мы пользуемся для своих последующих примеров Get-Process; вы можете придерживаться одной из трёх перечисленных, или переключаться между ними чтобы видеть разницу в получаемых результатах.

Что вы видите? Когда мы запускаем Get-Process, на нашем экране появляется некая таблица с несколькими столбцами сведений (Рисунок 6.2).

 

Рисунок 6-2


Вывод Get-Process это некая таблица с несколькими столбцами сведений

Прекрасно получать эти сведения на своём экране, однако вы можете пожелать делать нечто большее с этой информацией. Например, если вы пожелаете выполнять диаграммы и графики использования памяти и ЦПУ, вы можете захотеть экспортировать эти сведения в некий файл CSV, который можно будет считать в неком приложении для последующих манипуляций с данными.

Экспорт в CSV

Экспорт в это именно то, где становятся удобными конвейер и вторая команда:


Get-Process | Export-CSV procs.CSV
		

Аналогично передаче Dir в more, мы перенаправляем свой процесс в Export-CSV. Этот второй командлет обладает обязательным позиционным параметром (обсуждались в Главе 3), который мы применяем для определения своего файла вывода. Поскольку Export-CSV естественный командлет PowerShell, он знает как транслировать получаемый Get-Process в стандартный файл CSV.

Двинемся далее и откроем полученный файл в Visual Studio Code для просмотра полученных результатов, как это отражено на Рисунке 6.3.


code ./procs.CSV
		
 

Рисунок 6-3


Просмотр экспортируемого файла CSV в Блокноте Windows

Самая первая строка этого файла содержит заголовки столбцов, а последующие строки перечисляют все сведения для имеющихся различных процессов, запущенных в вашем компьютере. Вы можете пересылать вывод практически любого командлета Get- в Export-CSV и получать исключительные результаты. Вы также можете отметить, что получаемый файл CSV содержит намного больше сведений чем обычно отображается на экране. Это преднамеренно. Оболочка знает, что она не способна разместить на экране эти сведения, поэтому она применяет предоставленную Microsoft конфигурацию для выбора под отображение на экране наиболее важной информации. В последующих главах мы покажем вам как переопределять такую конфигурацию для отображения всего что вы пожелаете.

После того как все сведения сохранены в файле CSV, вы запросто можете отправлять его коллегам через электронную почту и просить просмотреть их через PowerShell. Для этого им придётся импортировать ваш файл:


Import-CSV procs.CSV
		

Их оболочка считает полученный файл CSV и отобразит сведения о ваших процессах. Они не будут основаны на информации в реальном времени, однако это будет моментальный снимок в точности того момента времени, в который был создан ваш файл CSV.

Экспорт в JSON

Давайте допустим, что вы желаете выполнить экспорт сведений о своих процессах и включит информацию об их потоках. Сведения о потоках это то, что носит название вложенных свойств в объекте process. Давайте взглянем (Рисунок 6.4). Обратите внимание на то, что Select-Object Threads сообщает PowerShell отображать только свойство Threads. Более глубоко мы рассмотрим Select-Object в Главе 8.

 

Рисунок 6-4


Мы показываем два различных способа отображения свойства Threads

Когда вы попробуете выполнить экспорт при помощи ConvertTo-CSV, свойство Threads будет обладать значением System.Diagnostics.ProcessThreadCollection. итак, нам необходим иной способ экспорта данных когда мы нуждаемся во вложенных свойствах под свойством Threads.

PowerShell также обладает командлетом ConvertTo-Json, который создаёт файл JSON, который всегда сохраняет такие вложенные свойства. Большинство языков программирования обладают библиотеками, понимающими JSON. У вас также имеется соответствующий командлет ConvertFrom-Json. И командлет ConvertFrom, и командлет ConvertTo (также как и ConvertFrom-CSV с ConvertTo-CSV) и производят, и потребляют строки в своём конвейере. Именно такая команда служит для преобразования процессов в JSON, применяя Out-File для сохранения получаемых результатов в файл:


PS C:\Scripts\> Get-Process | ConvertTo-Json | Out-File procs.json
		

Вы можете вернуть данные обратно, выполнив следующую команду:


PS C:\Scripts\> Get-Content ./procs.json | ConvertFrom-Json
		

Если вы исполните данную команду, вы отметите что ваши данные в совершенно ином формате по сравнению с тем когда вы запускаете команду Get-Process. В своём следующем разделе мы покажем вам как их обрабатывать. Рисунок 6.5 отображает некую выдержку того как выглядят получаемые свойства Threads при экспорте в JSON.

 

Рисунок 6-5


Показываем как свойство Threads выглядит в формате JSON

Экспорт в XML

В своём предыдущем разделе вы обратили внимание на то, что возвращаемые ConvertFrom-Json отображаются совершенно иначе по сравнению с тем, когда вы получаете их первоначальной командой. Это обусловлено тем, что ваши объекты не обладают одним и тем же типом (в Главе 8 мы рассмотрим объекты). Существует команда для экспорта данных и получения обратно самих первоначальных объектов.

PowerShell обладает командлетом Export-Clixml, который создаёт естественный файл CLI XML, позволяющий PowerShell реконструировать свои первоначальные объекты (или нечто очень близкое к ним). Clixml уникален для PowerShell, и хотя все программы технически способны понимать производимый им XML, будет лучше когда результаты применяются самим PowerShell. У вас также имеется соответствующий командлет Import-Clixml. И командлет импорта, и командлет экспорта (также как и Import-CSV с Export-CSV) ожидают названия файла в качестве обязательного параметра.

[Замечание]Когда применять Export-Clixml

Если мы получаем первоначальные объекты лучше, почему бы нам не пользоваться им постоянно? Имеется ряд недостатков:

  • Данный формат обладает намного большим размером.

  • Этот формат специфичен для PowerShell и может быть сложным для считывания в прочих языках программирования.

  • В Windows, PowerShell будет шифровать связанные с безопасностью порции такого файла, что подразумевает, что такой файл может быть расшифрован только теми пользователем или машиной, которые создали данный файл.

[Совет]Попробуйте прямо сейчас

Попробуйте выполнить экспорт таких вещей как процессы или команды в некий файл CLIXML. Убедитесь что вы способны повторно импортировать такой файл и попробуйте открыть получаемый в результате файл в Visual Studio Code или ином текстовом редакторе в своей системе чтобы увидеть как приложение отображает полученные сведения.

Содержит ли PowerShell иные команды импорта или экспорта? Вы можете отыскать их воспользовавшись командлетом Get-Command и предписав параметр -Verb либо с Import, либо с Export.

[Совет]Попробуйте прямо сейчас

Проверьте поступает ли PowerShell с какими- нибудь ещё командлетами импорта или экспорта. Вы можете пожелать повторить такую проверку после загрузки новых команд в свою оболочку - нечто, что мы проделаем в своей следующей Главе.

Out-File

Мы обсудили файлы CSV, JSON и XML, но что если мы пожелаем просто текстовый файл для сохранения в нём ваших данных? Давайте взглянем на команду Out-File. Она получает содержащиеся в своём конвейере данные и отправляет их в простой файл - ниже приводится некий текстовый файл для нашего примера:


Get-ChildItem | Select-Object Name | Out-File process.txt
		

Сопоставление файлов

И файлы CSV, и файлы CLIXML могут быть полезными дня неизменных моментальных снимков сведений, совместного применения этих снимков с прочими и просмотра этих снимков позднее по времени. Фактически, Compare-Object предлагает великолепный способ их применения.

Прежде всего выполните help Compare-Object и прочтите получаемую подсказку для этого командлета. Мы хотим чтобы вы, в частности, уделили три параметра: -ReferenceObject, -DifferenceObject и -Property.

Compare-Object разработан для получения двух наборов сведений и их сопоставления друг с другом. Например, допустим вы выполнили Get-Process в двух компьютерах, располагающихся бок о бок. Тот компьютер, который настроен в точности тем способом, расположен слева и является Эталонным компьютером. Компьютер справа может быть точно таким же, либо может чем- то отличаться; это Не совпадающий компьютер. После выполнения команды в каждом из них, вы начинаете с двух таблиц информации, причём ваше задание состоит в определении тех отличий, которые имеются между этими двумя.

Поскольку это просматриваемые вами процессы, вы всегда ожидаете наблюдать отличия в таких моментах как числа использования ЦПУ и памяти, поэтому мы игнорируем такие столбцы. Фактически, мы сосредоточиваемся на столбце Названий, поскольку мы хотим определить содержит ли Не совпадающий компьютер какие- то дополнительные процессы или их меньше по сравнению с Эталонным компьютерам. Для сравнения всех названий процессов из двух таблиц может потребоваться некоторое время, но от вас этого не потребуется - именно это для вас сделает Compare-Object. Допустим, вы располагаетесь за Эталонным компьютером и выполняете это:


Get-Process | Export-CliXML reference.xml
		

Мы предпочитаем применять CLIXML вместо CSV для сравнения подобного, поскольку CLIXML содержит больше сведений чем простой файл CSV. Затем вы можете перенести этот файл XML на Не совпадающий компьютер и выполняем такую команду:


Compare-Object -Reference (Import-Clixml reference.xml)
➥-Difference (Get-Process) -Property Name
		

Поскольку наш предыдущий шаг слегка хитроумен, мы поясним что происходит:

  • Как и в математике, скобки в PowerShell управляют установленным порядком исполнения. В нашем предыдущем примере они заставляют Import-Clixml и Get-Process исполнять до выполнения Compare-Object. Получаемый вывод из Import-Clixml наполняет параметр -Reference, а получаемый из Get-Process вывод заполняет параметр -Difference.

    Значениями названий параметров являются -ReferenceObject и -DifferenceObject. Имейте в виду что вы можете сокращать названия параметров при наборе достаточной для оболочки части их имён чтобы иметь возможность определить что именно вы хотите. В данном случае -Reference и -Difference это больше чем достаточно для уникальной идентификации данных параметров. Вероятно, мы могли бы иметь ещё более короткие, чем- то вроде -ref и -diff, а наша команда всё ещё будет продолжать работать.

  • Вместо того чтобы сопоставлять такие две таблицы полностью, Compare-Object останавливается на Name, поскольку мы придали его в параметр -Property. Если бы мы этого не сделали, он бы считал что все процессы отличаются, поскольку имеющиеся в таких столбцах как VM, CPU, PM значения всегда имеют тенденцию отличаться.

  • Получаемый результат это некая таблица, сообщающая вам в чём состоят отличия. Всякий процесс из Эталонного набора, но отсутствующий в Не совпадающем наборе будет иметь указатель <= (который указывает что данный процесс присутствует лишь в левой таблице). Когда процесс имеется в Не совпадающем компьютере, но отсутствует в Эталонном компьютере, вместо этого он будет обладать указателем =>. Те процессы, которые соответствуют обоим наборам не включаются в получаемый в Compare-Object вывод.

[Совет]Попробуйте прямо сейчас

Пройдите далее и попробуйте это. Если у вас нет двух компьютеров, начните с экспорта ваших текущих процессов в файл CLIXML, как это показано в предыдущем примере. Затем запустите некие дополнительные процессы, иной pwsh, например Visual Studio Code, nano (редактор командной строки), браузер или игру. Ваш компьютер превратится в Не совпадающий компьютер (в правый), в то время как файл CLIXML всё ещё будет служить для Эталонного компьютера (левого).

Вот получаемый в наше проверке вывод:


PS C:\Scripts>Compare-Object -ReferenceObject (Import-Clixml ./procs.xml) 
     ➥ -DifferenceObject (Get-Process) -Property name
 
name            SideIndicator
----            -------------
nano            =>
pwsh            =>
		

Это полезный приём управления. Когда вы представляете себе такие файлы CLIXML в качестве конфигураций базового уровня, вы можете сопоставлять любой текущий компьютер с таким базовым уровнем и получать отчёт об отличиях. На протяжении данной книги вы обнаружите дополнительные командлеты, которые способны выполнять выборку сведений, причём все они могут переправляться в некий файл CLIXML для превращения в базовый уровень. Вы быстро можете создать коллекцию файлов базового уровня для служб, процессов, конфигурации операционной системы, пользователей и групп и многого иного, а затем пользоваться ими всякий раз для сопоставления с текущим состоянием системы с данным базовым уровнем.

[Совет]Попробуйте прямо сейчас

Шутки ради, попробуйте выполнить свою команду Compare-Object снова, но на этот раз удалите целиком параметр -Property. Видите результат? Перечислены все отдельные процессы, поскольку такие значения как PM, VM и тому подобные, все они отличаются, даже для тех же самых процессов. Получаемый вывод к тому же бесполезен, поскольку он отображает все названия типов процессов и имён процессов.

Между прочим, вам следует знать, что Compare-Object обычно плохо справляется со сравнением текстовых файлов. Хотя в прочих операционных системах и оболочках имеется команда Compare-Object, в явном виде предназначенная для сравнения текстовых файлов, в PowerShell команда Compare-Object работает иначе. Как именно иначе вы увидите в лабораторных занятиях для этой главы.

[Замечание]Замечание

Если вам кажется, что вы часто пользуетесь Get-Process и Get-Command, да, это сделано намеренно. Мы гарантируем, что у вас имеется доступ к этим командлетам, поскольку они встроены в PowerShell и не требуют надстроек, таких как Azure PowerShell или AWS Tools для PowerShell. Тем не менее, изучаемые вами навыки применимы и ко всем командлетам, которые вам придётся запускать, включая и те, которые поставляются с модулями Azure compute, Azure Storage, Azure Virtual Network и Azure PowerShell.

Конвейер в файл

Всякий раз когда у вас имеется хорошо отформатированный вывод,к примеру, выработанные Get-Command или Get-Process таблицы - вы можете сохранить их в неком файле или даже на бумаге. Как правило, вывод командлета направляется на ваш экран, на который PowerShell ссылается как на хост, однако вы можете изменять куда поступает этот вывод. Мы уже показали вам один способ выполнения этого:


Dir > DirectoryList.txt
		

Символ > это добавленное в PowerShell сокращение для предоставления совместимости с оболочкой Bash. На практике, при исполнении вами данной команды вот что происходит под капотом PowerShell:


Dir | Out-File DirectoryList.txt
		

Вы можете исполнить ту же самую команду самостоятельно, вместо использования синтаксиса >. Зачем нам это По той причине, что Out-File к тому же предоставляет дополнительные параметры, которые позволяют указывать альтернативные кодировки символов (например, UTF-8 или Unicode), добавлять содержимое в конец файла и тому подобное. По умолчанию, созданные Out-File файлы обладают шириной столбцов 80, что означает, что иногда PowerShell способен изменять вывод команды чтобы он умещался в пределах 80 символов. Такое изменение может приводить к тому, что содержимое файла будет выглядеть иначе, нежели при выполнении той же самой команды на ваш экран. Чтобы узнать как вы можете изменять ширину файла вывода на нечто, отличающееся от 80 символов, ознакомьтесь с файлом подсказки Out-File.

[Совет]Попробуйте прямо сейчас

Не ищите здесь ответ - откройте данный файл подсказки и посмотрите что вы можете отыскать. Мы гарантируем, что через несколько минут вы отыщите нужный параметр.

PowerShell обладает разнообразными командами Out-. Одна из них носит название Out-Default, и именно она применяется когда вы не определяете иной командлет Out-. Если вы исполняете


Dir 
		

технически вы запускаете


Dir | Out-Default
		

даже если вы и не отдаёте себе отчёт в этом. Out-Default это ничто иное, чем направление содержимого в Out-Host, что означает что вы выполняете


Dir | Out-Default | Out-Host
		

незаметно для себя. Out-Host отображает сведения на вашем экране. Какие иные команды Out- вы способны обнаружить?

[Совет]Попробуйте прямо сейчас

Настало время исследования командлетов Out-. Для начала попробуйте воспользоваться командой Help и символами замещения, например Help Out*. Другой вариант состоит в точно таком же применении команды Get-Command, например, Get-Command Out*. Либо вы можете определить параметр -Verb в Get-Command -Verb Out. На чём вы остановились?

Out-Null и Out-String обладают особым применением, которое мы не будем рассматривать, но вы можете прочесть их файлы подсказок и посмотреть содержащиеся в этих файлах подсказки.

Преобразование в HTML

Хотите производить отчёты HTML? Направьте свою команду в ConvertTo-Html. Эта команда производит достойно форматированный, общий HTML, который отображается в любом веб- браузере. Это выглядит просто, однако вы можете сослаться на файл Вложенных таблиц стилей (CSS, Cascading Style Sheets) для определения более привлекательного форматирования, если это требуется. Обратите внимание, что такая команда не требует имени файла:


Get-Process -Id $PID | ConvertTo-Html
		
[Совет]Попробуйте прямо сейчас

Убедитесь что вы исполнили эту команду самостоятельно - мы хотим чтобы вы увидели что она делает прежде чем продолжим.

В мире PowerShell глагол Export подразумевает, что вы берёте данные, преобразовываете их в некий иной формат и сохраняете этот другой формат в неком виде хранилища, например в файле. Значение глагола ConvertTo подразумевает лишь некую часть этого процесса: преобразование в иной формат, однако не сохраняя это в файле. Когда вы выполнили нашу предыдущую команду, вы получаете экран заполненный HTML, что, скорее всего, н было тем, что вы желали. Остановитесь на секунду; можете ли вы представить как вы получаете это HTML в текстовом файле на диске?

[Совет]Попробуйте прямо сейчас

Если вы способны придумать некий вариант, попробуйте его, прежде чем читать дальше.

Данная команда выполняет эту хитрость:


Get-Process | ConvertTo-Html | Out-File processes.html
		

Видели как соединение большего и большего числа команд позволяет вам обладать всё более мощными командными строками? Каждая команда обрабатывает один шаг в общем процессе, а вся командная строка в целом выполняет полезную задачу.

PowerShell снабжается и прочими командлетами ConvertTo-, включая ConvertTo-CSV и ConvertTo-Xml. Как и в случае с ConvertTo-Html, они не создают файл на диске; они транслируют вывод команды в CSV или HTML, соответственно. Вы можете перенаправлять такой преобразованный вывод в Out-File для последующего сохранения на диске, хотя и было бы короче воспользоваться Export-CSV или Export-Clixml, поскольку они выполняют и преобразование, и сохранение.

[Замечание]Дополнительно

Настало время для слегка бесполезной информации основ, хотя в данном случае это ответ на вопрос, который задают многие студенты: зачем Microsoft предоставлять и Export-CSV, и ConvertTo-CSV, а также два почти одинаковых командлета для XML?

В некоторых сложных обстоятельствах вы можете пожелать не сохранять данные в файле на диске. Например, вам может понадобиться преобразовать данные в XML, а затем передать из в некую веб- службу или иное место назначения. Обладая обособленными командлетами ConvertTo-, которые не выполняют сохранение в файл, вы можете выполнять всё что пожелаете.

Применение командлетов, которые изменяют саму систему: уничтожение процессов

Экспорт и преобразование не единственные причины, по которым вы можете желать соединение двух команд воедино. Например, рассмотрим - однако будьте любезны не выполнять её - такую команду:


Get-Process | Stop-Process
		

Вы можете представит себе что сделает данная команда? Мы скажем вам: вы можете уничтожить критически важные процессы. Она выполнит выборку всех процессов и затем попытается завершить каждый из них. Она способна получить некий критически важный процесс, такой как /usr/sbin/coreaudiod в macOS, а ваш компьютер больше не будет способен воспроизводить звук. Если вы запустили PowerShell внутри виртуальной машины и хотите побаловаться, следуйте дальше и попробуйте выполнить эту команду.

Дело в том, что командлеты с одним и тем же существительным (в данном случае Process) часто способны обмениваться между собой сведениями. Обычно вам приходится указывать конкретное название определённого процесса вместо того чтобы пытаться остановить их все:


Get-Process -Name bash | Stop-Process
		

Задания (jobs) предоставляют нечто аналогичное: получаемый из Get-Job вывод может быть переправлен в такие командлеты как Stop-Job, Receive-Job, Wait-Job и тому подобные. Подробнее задания мы рассмотрим в Главе 14.

Как вы можете предположить, определённые правила ограничивают то, какие команды могут соединяться друг с другом. Например, когда вы ищите такую последовательность как Get-Process | New-Alias, вы, скорее всего, не ожидаете что она сделает нечто чувствительное (хотя она и способна выполнить нечто несуразное). В Главе 7 мы окунёмся в те правила, которые руководят тем как команды способны соединяться друг с другом.

Нам бы хотелось ознакомиться ещё с одним моментом относительно таких командлетов как Stop-Job и Stop-Process. Эти командлеты изменяют неким образом саму систему, а все командлеты, которые изменяют вашу систему обладают внутренне определённым уровнем влияния (impact level). Сам создатель командлета устанавливает такой уровень влияния и он может быть изменён. Соответствующая оболочка обладает надлежащей установкой $ConfirmPreference, которая по умолчанию настроена на High. Чтобы увидеть настройку своей оболочки наберите следующее название установки:


PS /Users/jsnover> $ConfirmPreference
High
		

Вот как это работает: когда внутренний уровень влияния командлета равен или выше настройки $ConfirmPreference оболочки, такая оболочка автоматически спросит: "Are you sure?" (Вы уверены?) когда данный командлет попробует что- то предпринять. Если вы применяете виртуальную машину чтобы попробовать крушащую- ваш - компьютер команду, которую мы упоминали ранее, у вас, скорее всего спросят "Are you sure?" для каждого процесса. Когда внутренний уровень влияния меньше чем настройка $ConfirmPreference оболочки, вы не получите автоматического предложения на ввод "Are you sure?". Однако вы можете принудить свою оболочку спрашивать вас каждый раз, уверены ли вы:


Get-Process | Stop-Process -Confirm
		

Вы просто добавляете в свой командлет параметр -Confirm. Он должен поддерживаться всеми командлетами, которые вносят изменения некого вида в саму систему и это будет отражено в файле подсказки для такого командлета в случае поддержки.

Аналогичным параметром выступает -WhatIf. Он поддерживается всеми поддерживающими -Confirm командлетами. Такой параметр -WhatIf не включается по умолчанию, однако вы можете задавать его всякий раз, когда пожелаете:


PS C:\Scripts > Get-Process | Stop-Process –WhatIf
What if: Performing operation "Stop-Process" on Target "conhost (1920)
".
What if: Performing operation "Stop-Process" on Target "conhost (1960)
".
What if: Performing operation "Stop-Process" on Target "conhost (2460)
".
What if: Performing operation "Stop-Process" on Target "csrss (316)".
		

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

Общие моменты путаницы

Одним из распространённых замешательств в PowerShell связано с командами Export-CSV и Export-Clixml. Технически говоря, обе команды создают текстовые файлы. Получаемый в каждой из команд вывод можно просмотреть в Visual Studio Code, как это отражено на Рисунке 6.3. Но надо признать, что этот текст пребывает определённом формате - будь то CSV, либо XML.

Собственно путаница происходит когда некто просит считать эти файлы обратно в оболочку. Воспользуетесь ли вы Get-Content (либо его type псевдонимом)? Скажем, допустим, вы сделали это:


PS C:\Scripts>Get-Process | Select-Object -First 5 | export-CSV processes.CSV 
➥ -IncludeTypeInformation
		

Обратите внимание на установленный переключатель -IncludeTypeInformation; мы вернёмся к нему позднее. Теперь попробуем считать это обратно воспользовавшись Get-Content:


PS C:\Scripts>Get-Content ./processes.CSV                                    
#TYPE System.Diagnostics.Process "Name","SI","Handles","VM","WS","PM","NPM","Path",
"Parent","Company","CPU","FileVersion","ProductVersion","Description","Product","__NounName","SafeHandle",
"Handle","BasePriority","ExitCode","HasExited","StartTime","ExitTime","Id","MachineName","MaxWorkingSet",
"MinWorkingSet","Modules","NonpagedSystemMemorySize64","NonpagedSystemMemorySize","PagedMemorySize64",
"PagedMemorySize","PagedSystemMemorySize64","PagedSystemMemorySize","PeakPagedMemorySize64",
"PeakPagedMemorySize","PeakWorkingSet64","PeakWorkingSet","PeakVirtualMemorySize64","PeakVirtualMemorySize",
"PriorityBoostEnabled","PriorityClass","PrivateMemorySize64","PrivateMemorySize","ProcessName",
"ProcessorAffinity","SessionId","StartInfo","Threads","HandleCount","VirtualMemorySize64","VirtualMemorySize",
"EnableRaisingEvents","StandardInput","StandardOutput","StandardError","WorkingSet64","WorkingSet",
"SynchronizingObject","MainModule","MainWindowHandle","MainWindowTitle","Responding",
"PrivilegedProcessorTime","TotalProcessorTime","UserProcessorTime","Site","Container"
"","87628","0","0","0","0","0",,,,,,,,,"Process",
"Microsoft.Win32.SafeHandles.SafeProcessHandle","0","0",,"False",,,"0",".",,,"System.Diagnostics.ProcessModuleCollection",
"0","0","0","0","0","0","0","0","0","0","0","0","False",
"Normal","0","0","",,"87628",,"System.Diagnostics.ProcessThreadCollection","0","0","0",
"False",,,,"0","0",,,"0","","True",,,,,
		

Мы усекли свой предыдущий вывод, но в нём ещё много подобного. Выглядит как мусор, не так ли? Вы просматриваете сырые данные CSV. Наша команда не пытается интерпретировать или разбирать полученные данные вовсе. В противоположность с результатами Import-CSV:


PS C:\Scripts>Import-CSV ./processes.CSV
 NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName
 ------    -----      -----     ------      --  -- -----------
      0     0.00       0.00       0.00       0 ...28 
      0     0.00       0.00       0.00       1   1 
      0     0.00       0.00       0.00      43  43 
      0     0.00       0.00       0.00      44  44 
      0     0.00       0.00       0.00      47  47
		

Намного лучше, ведь так? командлеты Import- уделяют внимание тому что содержится в самом файле, пытаясь интерпретировать это и создают отображение, которое выглядит во многом как вывод своей первоначальной команды (в данном случае Get-Process). Чтобы осуществить это с Export-CSV, вам необходимо воспользоваться переключателем -IncludeTypeInformation. Обычно затем, когда вы создали при помощи Export-CSV некий файл, вы считываете его при помощи Import-CSV. Если вы создали его при помощи Export-Clixml, вы обычно считываете его применяя Import-Clixml. Используя данные команды попарно вы достигаете лучшего результата. Пользуйтесь Get-Content только когда вы считываете текстовый файл и не желаете чтобы PowerShell пытался выполнять синтаксический разбор предоставляемых данных - то есть когда вы желаете работать с сырыми данными.

Лабораторные занятия

Мы сделали текст данной главы намного более коротким, потому как некоторые примеры, скорее всего, отняли у вас слегка больше времени, и мы хотим, чтобы в затратили больше времени на выполнение следующих практических упражнений. Если вы ещё пока не выполнили все задачи "Попробуйте прямо сейчас" из данной главы, мы настоятельно рекомендуем вам сделать это до выполнения приводимых ниже задач:

  1. Создайте два аналогичных, но имеющих отличия файла. Попробуйте сопоставить их при помощи Compare-Object. Выполните нечто подобное этому: Compare-Object -Reference (Get-Content File1.txt) -Difference (Get-Content File2.txt). Когда файлы обладают отличием только в одной строке текста, данная команда должна работать.

  2. Что происходит когда вы запускаете Get-Command | Export-CSV commands.CSV | Out-File из своей консоли? Почему это происходит?

  3. Помимо получения одного или нескольких заданий с их передачей в Stop-Job, какие иные средства предоставляет вам Stop-Job для указания задания или заданий, которые вы желаете остановить? Можно ли остановить задания вовсе не применяя Get-Job?

  4. Что предпринять если вы желаете создать файл с разделителями вертикальной чертой вместо типа файла CSV? Вы по- прежнему можете применять команду Export-CSV, но какие параметры вы укажете?

  5. Как вы включите сведения о типе в строке комментария # в самом верху экспортируемого файла CSV?

  6. И Export-Clixml, и Export-CSV, оба, изменяют вашу систему, поскольку они способны создавать и перезаписывать файлы. Какие параметры предотвратят от перезаписи ими имеющегося файла? Какой параметр запросит уверены ли вы перед тем как выполнить запись в файл вывода?

  7. Ваша операционная система поддерживает различные региональные установки, которые содержат и установленный по умолчанию разделитель списка. В системах US таким разделителем выступает запятая. Как вы можете указать Export-CSV о необходимости применения установленного по умолчанию разделителя вместо запятой?

Ответы лабораторных занятий

  1. PS C:\Scripts > "I am the walrus" | Out-File file1.txt

    PS C:\Scripts > "I'm a believer" | Out-File file2.txt

    PS C:\Scripts > $f1 = Get-Content .\file1.txt

    PS C:\Scripts > $f2 = Get-Content .\file2.txt

    PS C:\Scripts > Compare-Object $f1 $f2

    InputObject                             SideIndicator

    -----------                             -------------

    I'm a believer                          =>

    I am the walrus                         <=

  2. Когда вы не определяете название файла при помощи Out-File, вы получаете некую ошибку. Но даже когда вы это делаете, Out-File не сделает ничего, потому как необходимый файл создаётся Export-CSV.

  3. Stop-Job способен принимать одно или более названий заданий в качестве значения параметра для параметра –Name. Например, вы можете поступить так:

    
    Stop-job jobName
    		
  4. get-Command | Export-CSV commands.CSV -Delimiter "|"

  5. Воспользуйтесь параметром –IncludeTypeInformation для Export-CSV.

  6. Get-Command | Export-CSV services.CSV –NoClobber

    Get-Command | Export-CSV services.CSV -Confirm

  7. Get-Command | Export-CSV services.CSV -UseCulture