Powershell дописать в файл csv

Обновлено: 05.07.2024

Здесь мы рассмотрим некоторые возможности powershell при сохранении данных в файл. Этот функционал применяется практически всегда, когда речь заходит о больших выгрузках, о результатах работы каких-либо автоматизаций. Банальным примером будет настройка логирования выполнения скрипта в планировщике задач.

Экспорт данных в файл. Add-Content, Set-Content

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

Синтаксис группы этих команд идентичен друг другу и достаточно прост. Чтобы получить содержимое файла, необходимо просто указать путь к файлу в параметре -Path:

Out-File

В этом примере перед сохранением в файл данные конвертируются в HTML код. И Вы можете сохранить их в HTML документ. При этом возможно вносить элементы форматирования страницы, используя CSS. Если есть необходимость просто сохранить данные на диск в первозданном виде, тогда необходимо просто использовать командлет Out-File.

Некоторые полезные параметры:

Export-Csv

Этот вид экспорта наиболее подходит и чаще всего применяется для формирования табличных выгрузок или отчетов. В параметрах этого командлета есть возможность указать, какой символ будет служить разделителем. Для демонстрации выгрузим все виртуальные машины на хосте виртуализации в файл .csv. Подробнее ►

В результате будет получен файл примерно следующего вида и содержания:

Как Вы видите, теперь содержимое файла автоматически распределилось по колонкам. А чтобы из шапки документа убрать тип выгружаемых данных, к команде необходимо добавить параметр -NoTypeInformation .

Импорт данных из файла. Get-Content

Если есть необходимость загрузить в скрипт содержимое файла для его обработки, тогда Вы можете использовать Get-Content. В таком случае в результате выполнения Вы получите одномерный массив объектов. Где каждая строка будет являться независимым друг от друга объектом. Подробнее ►

Пример работы Get-Content

Пример работы Get-Content

Import-CSV

Как и в случае с экспортом в csv, импорт имеет возможность указать разделитель. Таким образом в результате импорта у каждого объекта (строки) будет набор параметров, соответствующий названиям колонок в файле. И к этим параметрам можно обращаться программно.

Выполним обратную процедуру и импортируем список виртуальных машин.

Пример работы Import-CSV

Пример работы Import-CSV

Анонс следующей статьи: “Операторы сравнения или логические операторы”.

Игорь Чердаков

Мне 32 года. На текущий момент я являюсь администратором систем Microsoft в одной из крупнейших компаний в России. За моими плечами практически 7 лет опыта работы в IT, последние 3 из которых в администрировании. Сопровождая немалую инфраструктуру, в ежедневной деятельности я сталкиваюсь с необходимостью автоматизации рутинных процессов, в чем мне успешно помогает Powershell. Данный блог основывается на моем личном опыте и знаниях. Мои статьи не являются истиной в последней инстанции и я положительно отношусь к обоснованной и конструктивной критике. По этому я приглашаю Вас обсуждать волнующие нас вопросы, связанные с Powershell.

Классическая оболочка Cmd.exe в операционных системах Windows предоставляет очень простые средства для обработки текстов. Например, команда For /f позволяет читать строки текста из файла и обрабатывать их как одну строку, а оператор > дает возможность писать выходные данные команды в текстовый файл.

Однако простой построчный анализ текста дает сбой в том случае, если вам нужно обработать структурированные данные. Например, файлы в формате CSV являются чрезвычайно распространенным форматом обмена данными. Я не могу даже сосчитать, сколько раз видел в онлайн-форумах вопрос: «как мне прочитать вводимые данные из файла формата CSV, используя пакетный файл (то есть набор команд оболочки Cmd.exe)»? Возможно, вам пришлось делать весь анализ вручную, а это крайне сложно. Например, если строка вводимых данных содержит специальные символы, такие как , вы не сможете выполнить анализ. Анализ файлов XML с помощью Cmd.exe даже более сложен. Если не сказать невозможен.

Windows PowerShell справляется с упомянутыми выше трудностями, предоставляя строку команд для импорта и экспорта структурированных данных. Все эти команды содержат в названии либо слово CSV, либо слово XML, поэтому вы можете получить их список, введя следующую команду в строке PowerShell:

Когда вы запускаете эту команду, вы видите список всех команд в сессии PowerShell, которые содержат в названии либо слова CSV и XML, либо какие-то дополнительные имена. Я расскажу о командах, которые содержат глаголы Export и Import.

Импорт файлов CSV

Как уже говорилось выше, CSV – это весьма распространенный формат для обмена данными. файл CSV является открытым текстовым файлом, который представляет собой таблицу данных. Каждая строка файла — это одна запись (строка) данных. Первая строка файла обычно (хотя и не всегда) определяет имена полей (столбцов). Элементы данных внутри каждой строки разделены символом разделителя. В качестве разделителя часто используется запятая (особенно когда дело касается текстовых данных), поэтому элементы данных в файле CSV обычно заключены в двойные кавычки («) или в какие-либо другие символы. В таблице приведен пример таблицы данных.

На экране 1 показано, как эти данные будут представлены в файле CSV.

Import-Csv читает файл CSV и выводит список пользовательских объектов PowerShell: один для каждой строки вводимых данных. PowerShell воспринимает первую строку файла CSV как свойства объекта, а последующие строки файла являются выводимыми объектами. Например, если вы запускаете команду Import-Csv Sample.csv, то PowerShell выведет три объекта с двумя свойствами для каждого: DisplayName и Mail, как показано на экране 2.

Если файл CSV, который вы хотите импортировать, не имеет строки заголовка, вы можете использовать параметр –Header для наименования свойств объекта. Таким образом, если бы в Sample1.csv отсутствовала первая строка (заголовок), вы бы использовали команду, например:

Import-Csv использует символ запятой, так как это разделитель по умолчанию, но вы можете применить параметр –Delimiter для определения иного символа для разделителя. Например, если бы Sample.csv использовал символ «табуляции» в качестве разделителя, вы бы вводили такую команду:

Поскольку Import-Csv выводит объекты PowerShell, вы можете задействовать другие команды PowerShell для обработки объектов. Например, предположим, что вы хотите рассортировать выводимые данные по критерию DisplayName, но вам нужно только свойство Mail для каждого объекта. Чтобы это сделать, вы используете команды Sort-Object и Select-Object:

Также вы можете передать эти объекты команде ForEach-Object для обработки:

Эта команда использует символ –f для вывода форматированной строки для каждого объекта и производит вывод данных, показанный на экране 3.

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

Заметьте, что Export-Csv может выводить данные любых объектов PowerShell, а не только объектов, созданных при помощи Import-Csv. Например, взгляните на такую команду:

Эта команда создает файл CSV, содержащий в текущей папке файлы, отсортированные по критерию размера. Эта команда использует Select-Object для выбора полного файлового имени каждого файла, времени последнего изменения и размера файла (длины). Таким образом, эти три свойства будут являться столбцами в файле CSV.

Импорт файлов XML

XML представляет собой другой тип текстового файла, который хранит структурированные данные. В листинге 1 приведен пример представления в XML данных из таблицы.

Данные в документе XML организованы в иерархическом порядке. В Sample.xml (листинг 1) у вас есть корневой элемент () и три дочерних элемента (). Элементы располагаются в парах и содержат другие элементы. Открывающий элемент использует угловые скобки вокруг своего имени, а закрывающий элемент использует косую черту перед именем элемента. Когда вы работаете с данными XML в PowerShell, вы должны иметь единственный корневой элемент. Другие элементы содержатся внутри корневого элемента.

В PowerShell есть команда Import-Clixml, но Import-Clixml не может импортировать Sample.xml, потому что Sample.xml не полностью соответствует формату, который требует cmdlet. Вместо него вы можете использовать Get-Content cmdlet и дополнительный тип обеспечения [Xml]: $Data = [Xml] (Get-Content Sample.xml).

После ввода команды переменная $Data содержит объект XmlDocument. Объект XmlDocument включает два свойства: xml (элемент в верхней части файла) и базу данных (корневой элемент). Вы можете вывести данные из файла XML так:

Эта команда производит точно такой же вывод данных, как показано на экране 2: выводит данные трех объектов с двумя свойствами для каждого (DisplayName и Mail).

Если данные файла XML, который вы хотите импортировать, были сохранены Export-Clixml, вам не нужен дополнительный акселератор типа [Xml] и команда Get-Content. Вместо них вы можете использовать Import-Clixml, о чем я расскажу в следующем разделе.

Экспорт Файлов XML

Вы можете экспортировать объект XmlDocument в файл, используя Export-Clixml. Как и Export-Csv, команда Export-Clixml требует имя файла. Рассмотрим такие команды:

Первая команда импортирует Sample.xml (листинг 1) в качестве объекта XmlDocument. Вторая команда экспортирует объект XmlDocument в Data.xml.

Import-Clixml противоположна Export-Clixml. Import-Clixml возвращает файл XML, который был экспортирован Export-Clixml в качестве объекта XmlDocument. Например, в следующей команде Import-Clixml возвращает Data.xml:

После запуска этой команды переменная $Data2 содержит копию того же объекта XmlDocument, который хранится в $Data.

Помните, что вы можете применять команду Import-Clixml для импорта только файла XML, созданного Export-Clixml. Это связано с тем, что файл XML должен содержать специфический набор элементов, чтобы Import-Clixml могла импортировать его. Если файл XML не в нужном формате, вам необходимо использовать дополнительный акселератор типа [Xml] и Get-Content, о чем говорилось в предыдущем разделе.

Управляйте файлами CVS и XML

Текстовые файлы CSV и XML представляют собой популярные форматы для обмена данными. Создатели PowerShell предоставили нам несколько весьма мощных и простых в использовании команд, которые помогают импортировать и экспортировать файлы в оба формата. Выполняемый вручную анализ файлов CSV и XML остался в прошлом.

У меня есть сценарий Powershell, который создает файл .csv с именами и адресами электронной почты. Я хотел бы иметь возможность добавлять строку с заголовком в начало файла.

Я могу сделать это с помощью текстового файла, но по какой-то причине мне не удается использовать файл .csv. Предложения?

2 ответа

Если вы хотите добавить в верхнюю строку CSV:

Чтобы добавить в CSV без удаления старых данных:

Я надеюсь, это поможет вам.

Существует стандарт IETF RFC 4180, который определяет, как создавать файл CSV и что он может и не может содержать. Чтобы напрямую ответить на ваш вопрос, нельзя добавить «заголовок» в файл CSV. Подводя итог спецификации, ваш файл должен иметь следующие

  1. Каждая строка данных разделяет данные на столбцы с помощью разделителя-запятой (знач1, знач2, знач3)
  2. Каждая строка заканчивается, а новая начинается с использования возврата каретки (val1, val2, val3 CRLF)
  3. Последняя строка в файле не содержит возврата каретки
  4. Необязательная строка заголовка может быть добавлена так же, как и обычная строка данных, и будет установлена путем включения параметра заголовка.

Как видите, стандартного способа установки «заголовка» не существует. Однако, если вы ссылаетесь на «заголовок» как на «заголовок», вы можете добавить его, используя следующие

Где a, b, c - ваши заголовки.

Ваши данные должны выглядеть следующим образом

Строка заголовка указывается как нечто отдельное от строк данных, включая следующий параметр mimetype

Как вы понимаете, единственными ограничениями являются параметр mimetype, разделитель и возврат каретки. Данные поля заключаются в двойные кавычки, если данные в этом поле содержат разрыв строки, запятую или двойные кавычки. Чтобы немного разбить Mimetype, тип мультимедиа - это текст, подтип - csv и два дополнительных параметра: заголовок и кодировка.

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

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

Если у вас есть дополнительные вопросы, не стесняйтесь добавлять комментарии, и я постараюсь ответить.

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

В данной статье описано, как записать и получить данные из файла при работе с PowerShell.

Операторы перенаправления.

Рассмотрим ещё один пример:

Get-ChildItem : Не удается найти путь "C:\temp\skdjfsdlj" , так как он не существует . + CategoryInfo : ObjectNotFound : ( C : \ temp \ skdjfsdlj : String ) [ Get-ChildItem ] , ItemNotFoundException + FullyQualifiedErrorId : PathNotFound , Microsoft . PowerShell . Commands . GetChildItemCommand Get-ChildItem : Не удается найти путь "C:\temp\skdjfsdlj" , так как он не существует . + CategoryInfo : ObjectNotFound : ( C : \ temp \ skdjfsdlj : String ) [ Get-ChildItem ] , ItemNotFoundException + FullyQualifiedErrorId : PathNotFound , Microsoft . PowerShell . Commands . GetChildItemCommand

После выполнения команды в файле будет записан как и результат выполнения команды, так и ошибки:

Get-ChildItem : Не удается найти путь "C:\temp\asdfsadf" , так как он не существует . + CategoryInfo : ObjectNotFound : ( C : \ temp \ asdfsadf : String ) [ Get-ChildItem ] , ItemNotFoundException + FullyQualifiedErrorId : PathNotFound , Microsoft . PowerShell . Commands . GetChildItemCommand

В этом примере мы перенаправили второй поток вывода в первый, а первый поток записали в файл.

В PowerShell существуют следующие потоки:

Set-Content, Add-Content

Так же для записи в файл можно использовать командлеты Set-Content и Add-Content. Эти командлеты заменяет все данные в файле на указанные. Перед записью они преобразовывают объекты в строки и не всегда удобны. Зато они могут использоваться для массового изменения файлов. Простейшая их запись выглядит так:

При работе с файловой системой командлеты могут применять следующие параметры:

В этом параметре нужно указывать новое содержимое элементов.

PS C : \ Temp > Add-content -Path 1 . txt -value "Hello1" , "Hello2"

Название параметра можно опустить, тогда предыдущие примеры будет выглядеть так:

Данный параметр, так же можно передавать по контейнеру.

Но в файл попадут не данные как на консоли, а преобразованные в текстовые строки объекты.

Тоже самое произойдёт, если в параметр -value передать переменную:

PS C : \ temp > Set-content -literalPath 1 . txt , 2 . txt "Hello"

или можно добавить данные:

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

-Force

+ CategoryInfo : NotSpecified : ( : ) [ Set-Content ] , UnauthorizedAccessException + FullyQualifiedErrorId : System . UnauthorizedAccessException , Microsoft . PowerShell . Commands . SetContentCommand PS C : \ temp > Set-content -Path "C:\temp\1.txt" -value "33" -force

Тоже самое и для Add-Content:

+ CategoryInfo : NotSpecified : ( : ) [ Set-Content ] , UnauthorizedAccessException + FullyQualifiedErrorId : System . UnauthorizedAccessException , Microsoft . PowerShell . Commands . SetContentCommand PS C : \ temp > Add-Content -Path "C:\temp\1.txt" -value "33" -force

В этом параметре можно указать шаблон имени файла.

PS C : \ temp > Set-content -Path "C:\temp\*" , "C:\temp2\*" -Filter "*.txt" -value "Hello2" PS C : \ temp > Set-content -Path "C:\temp\*" , "C:\temp2\*" -Include "*.doc" , "*.txt" -value "33" -Exclude "1.txt"

или добавить содержимое:

PS C : \ temp > Add-Content -Path "C:\temp\*" , "C:\temp2\*" -Include "*.doc" , "*.txt" -value "33" -Exclude "1.txt" PS C : \ temp > Set-content -Path * . txt -Exclude ? . txt "22"

Так же и для Add-Content:

PS C : \ temp > Add-Content -Path * . txt -Exclude ? . txt "22"

-PassThru

Данный параметр позволяет передать объекты дальше по контейнеру, или вывести объекты на консоль, если данный командлет является последним.

PS C : \ temp > Get-ChildItem | Set-Content 1 . txt -PassThru | gm Address Method System . Object & , mscorlib , Version =2 . 0 . 0 . 0 , Culture = neutral , PublicKeyToken = b77a5c561934 . . . CopyTo Method System . Void CopyTo ( array array , int index ) , System . Void CopyTo ( array array , long index )

-Confirm

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

Выполнение операции "Установка содержимого" над целевым объектом "Путь: C:\temp\1.txt" . [ Y ] Да - Y [ A ] Да для всех - A [ N ] Нет - N [ L ] Нет для всех - L [ S ] Приостановить - S [ ? ] Справка

Данные командлеты позволяют писать в файл только строки, для записи в файл объектов используются следующие командлеты:

Out-File

В простейшем варианте этот командлет выглядит так:

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

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

Имя данного параметра можно опустить, как мы и сделали в предыдущем примере.

Полная запись будет выглядеть так:

-Append

При указании данного параметра данные будут дописываться, а не затираться.

Тоесть если мы запустим команду:

-NoClobber

Данный параметр предотвращает перезапись существующих данных.

Если запусnить команду :

При уже имеющемся файле 2.txt

То получится ошибка:

+ get - childitem | Out - File < < < < - FilePath 2.txt - NoClobber + CategoryInfo : ResourceExists : ( C : \ temp \ 2.txt : String ) [ Out - File ] , IOException + FullyQualifiedErrorId : NoClobber , Microsoft . PowerShell . Commands . OutFileCommand

Однако с параметром -Append

get-childitem | Out-File -FilePath 2 . txt -NoClobber -Append

Сохранности данных ничего не угрожает и данные благополучно допишутся в конец файла.

-Confirm

Параметр указывает, что перед выполнением команды у пользователя будет запрошено подтвержение.

При выполнении данной команды:

Выполнение операции "Вывод в файл" над целевым объектом "2.txt" . [ Y ] Да - Y [ A ] Да для всех - A [ N ] Нет - N [ L ] Нет для всех - L [ S ] Приостановить - S [ ? ] Справка

-Force

То есть команда:

PowershellAndFiles3

При этом после записи в этот файл, галка не уберётся.

get-childitem 234234f 2 > &1 | Out-file 2 . txt -Encoding "ASCII"

Данный параметр позволяет сохранять в файл объект. При этом отображение этого объекта в консоли и сохраннёные данные в файл, могут визуально не совпадать

Например создадим вложенный массив :

Посмотрим на массив:

В данном примере и в файле и в консоле будет одно и тоже:

Запишем объект массива в файл, через параметр -InputObject:

Теперь в консоли будет выводиться :

Указывает максимальное кол-во символов в строке, при превышении данного значения, строка обрезается.

Получился вот такой файл:

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

Tee-Object

Этот командлет сохраняет отображаемые объекты и передаёт их дальше по контейнеру.

-FilePath

Так же с помощью свойства

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

Get-ChildItem * . txt | Tee-Object -Variable listfile | Get-Content

После выполнения этой команды в переменной $listfile будет содержаться объект типа System.IO.FileInfo

Так же как и в Out-File в Tee-Object можно передать переменную на командлет:

Только в PoverShell 3.0 Tee-Object научился дописывать в файл с помощью параметра

-Append

При использовании данного параметра файл будет не перезаписываться, а данные будут дописываться в конец файла.

Get-ChildItem * . txt | Tee-Object 3 . txt -Append | Get-Content

После выполнения данной командой данные допишутся в конец файла 3.txt, а не будут перезаписывать файл.

Get-Content

Для того, что бы получать данные из текстовых файлов, имеется командлет Get-Content.

У него есть ряд параметров, которые работают так же как и в Set-Content:

Задает путь к элементу. В отличие от значения параметра Path, значение параметра LiteralPath используется точно в том виде, в котором оно введено. Никакие символы не интерпретируются как подстановочные знаки. Если путь включает escape-символы, его нужно заключить в одиночные кавычки. Одиночные кавычки указывают оболочке Windows PowerShell, что никакие символы не следует интерпретировать как escape-символы.

PS C : \ Temp > Get-content -LiteralPath C : \ temp \ 1 . txt , C : \ temp \ 1 . txt , C : \ temp \ 1 . txt PS C : \ Temp > Get-content -LiteralPath C : \ temp \ 1 . txt , C : \ temp \ 1 . txt , C : \ temp \ 1 . txt | set-content 4 . txt PS C : \ Temp > Get-content -Path C : \ temp \ * . txt | set-content 5 . txt

Задает фильтр с использованием формата или языка поставщика. Значение этого параметра определяет значение параметра Path. Синтаксис фильтра, в том числе использование подстановочных знаков, зависит от поставщика. Фильтры эффективнее других параметров, потому что поставщик применяет их при извлечении объектов (вместо использования Windows PowerShell для фильтрации извлеченных объектов).

PS C : \ Temp > Get-content -Path C : \ temp \ * , C : \ temp2 \ * -filter * . csv | set-content 5 . csv Get-Content : Объект для указанного пути C : \ temp \ * не существует или отфильтрован с помощью параметра -Include или -Exc + Get-content < < < < -Path C : \ temp \ * , C : \ temp2 \ * -filter * . csv | set-content 5 . csv + CategoryInfo : ObjectNotFound : ( System . String [ ] : String [ ] ) [ Get-Content ] , Exception + FullyQualifiedErrorId : ItemNotFound , Microsoft . PowerShell . Commands . GetContentCommand PS C : \ Temp > Get-content -Path C : \ temp \ * -Include * . csv , * . txt | set-content 6 . txt Get-content -Path C : \ temp \ * -Exclude * . txt , * . csv | set-content 6 . doc

-Force

И два особенных параметра:

Данный параметр задает количество извлекаемых строк содержимого. По умолчанию используется значение -1 (все строки).

Данная команда вывела ровно 5 строк из файла 1.txt

Задаёт количество строк передаваемых по конвееру.

PS C : \ temp > Get-Content 1 . txt -ReadCount 5 | foreach < $_ + "-------" >

На примере видно, что строки передаются по 5 штук.

Если вывод происходит на консоль, то большое число в данном параметре может существенно увеличить скорость выдачи информации, но увеличит время ожидания до выдачи первых строк.

Данные команды конечно расширяют возможности работы с данными в файлах Powershell, но полученные данные с помощью операторов перенаправления или командлетами Out-File и Tee-Object больше подходят для логирования процессов, нежели для анализа данных. К тому же использовать полученные данные в дальнейших скриптах не тривиальная задача. Для решения этих проблем в PowerShell есть командлеты Import-CSV,Export-CSV, Export-Clixml, Import-Clixml. Рассмотрим их по отдельности:

Export-CSV

Раз я веду разговор о записи в файл, именно этот командлет мне нужен. Но стоит упоменуть о командлете ConvertTo-CSV. Так как Export-CSV выполняет все действия ConvertTo-CSV, а после записывает в файл. Поэтому если вам не хватает функционала работы с файлами командлета Export-CSV то вы можете конвертировать объекты PowerShell с помощью ConvertTo-CSV, а помом записать полученный результат удобным вам способом.

Рассмотрим свойства данного командлета:

Данный параметр обязательный и задаёт имя файла, в который будут записываться данные.

Читайте также: