Чтение и запись данных в excel файл из power shell

Получить данные их XLSX файла без установки Microsoft Office

Если вы хотите или не можете установить Excel на компьютере ( например у вас отсутствуют лицензии для активации Office или в случае с Windows Server Core), вы можете использовать кроссплатформенный PowerShell модуль ImportExcel для работы с Excel документами.

Установите модуль из PowerShell Gallery:

Рассмотрим типовые операции с книгами Excel, которые можно выполнить с помощью этого модуля.

Экспорт данных в XLSX файл:

Установка powershell модуля import-excel

Изменить значение в ячейке Excel:

С помощью PSObject можно добавить данные в таблицу Excel:

$FilePath = "C:\ps\ad_users.xlsx"
$ExcelData = Import-Excel -Path $FilePath -WorksheetName "AD_User_List"
$NewUser = [PSCustomObject]@{
  "UserName" = "aivanov"
  "FullName" = "Иванов Андрей"
  "Job" = "Инженер"
}
$ExcelData += $NewUser
Export-Excel -Path $FilePath -WorksheetName "AD_User_List" -InputObject $ExcelData

Добавить данные в лист excel файла из powershell

Как работать?

Я не буду рассказывать, как установить IM, просто оставлю ссылку. Ближе к низу страницы под надписью Windows Binary Release. Устанавливается просто из exe файла. После установки IM становится доступен как команда Powershell или командной строки, с чего мы и начнем.

Первое что нужно отметить – писать сразу в 1С – не удобно. Куда проще сделать скрипт в PS, а потом уже перенести его в 1С. Для задач начальной разработки отлично подходит Powershell ISE: Нужно лишь создать файл .ps1. К слову, ISE решает каким-то образом и другую проблему обычного Powershell – кириллицу. Я не суперуверенный пользователь Powershell и у меня русскоязычный Windows Server, поэтому первое столкновение с “powershellexe завершил свою работу” при вводе пути до картинки с кириллическими символами, вызвало у меня фрустрацию. Возможно у вас таких проблем с кодировкой не будет (или вы знаете, как их решить), но если нет, то ISE – ваш лучший друг.

Команды (командлеты) PowerShell

В языке программы PowerShell команды носят название командлеты (от английского «cmdlet»). Все они формируются с использованием шаблона «Глагол-Существительное», или «Действие-Объект». Например, Get-Services и Start-Process. Благодаря такой структуре, можно легко понять предназначение команды, даже если вы с ней ещё не работали ранее.

Синтаксис командлетов

После имени самого командлета следует указание параметров и их значений. Между всеми частями команды следует проставлять пробелы. Вот пример синтаксиса командлета, который позволяет перейти в директорию C:\:

Set-Location -LiteralPath C:\ -PassThru

Разберем его на составные части:

  • Set-Location — буквально «вызвать команду». Этот командлет позволяет выполнять указанный блок сценария.
  • -LiteralPath C:\ — здесь передаем блок сценария, в котором используется команда Set-Location для перехода в каталог C:\.
  • -PassThru — по умолчанию командлет Invoke-Command не возвращает результат выполнения. Этот параметр указывает на необходимость вывода информации о местоположении, в которое был выполнен переход с помощью команды Set-Location.
переход в директорию C в powershell

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

sEt-loCATion -PATH c:\ -passthru

Когда в одной строке объединены несколько команд, они разделяются точкой с запятой ;.

Иногда команда может быть слишком длинной. Для разделения на несколько строк можно использовать символ обратного апострофа ` в месте переноса. Новую строку можно создать, нажав Shift + Enter (для переноса строки ниже текущей) или Ctrl + Enter (для переноса строки выше текущей).

Разделим предыдущую команду:

Set-Location `
-LiteralPath C:\ `
-PassThru
разделение длинной команды в powershell обратным апострофом для переноса на новую строку

Алиасы

В процессе работы с терминалом иногда может быть неудобно постоянно вводить полные названия командлетов. Именно поэтому у наиболее часто используемых командлетов существуют псевдонимы (алиасы) — их сокращенные варианты.

Чтобы получить список доступных алиасов, вы можете воспользоваться командой Get-Alias. Кроме того, данной команде также доступен псевдоним gal.

список доступных алиасов в powershell

Чтобы получить список алиасов для конкретного командлета, вы можете использовать параметр -Definition. Пример:

Get-Alias -Definition Set-Location
список алиасов командлета set-location в powershell

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

# Оба следующих варианта эквивалентны:
Get-Alias -Name clear
Get-Alias clear
работа параметра -Name в PowerShell

Особенности обработки путей к каталогам

Для многих командлетов необходимо предоставить путь к файлу или каталогу. Это делается с использованием строки, например: C:\Windows\System32.

Однако, если в пути встречается пробел или другой специальный символ, PowerShell будет рассматривать его как разделитель. Например:

# Следующая команда не будет выполнена корректно
Set-Location C:\Program Files
пример некорректной команды в powershell: не удается найти позиционный параметр

PowerShell «воспринимает» пробел и интерпретирует его так, будто путь к папке закончился на слове Program, а files — это уже значение другого параметра.

Чтобы избежать подобных ситуаций, существует два метода:

  • Экранировать символы с помощью обратного апострофа `: C:\Program` Files. Однако это может быть неудобным, если путь длинный.
  • Поместить весь путь в одинарные или двойные кавычки: 'C:\Program Files' или "C:\Program Files" (желательнее использовать одинарные кавычки).

Кроме того, в PowerShell существуют сокращения для быстрого доступа к ближайшим директориям:

  • Точка . указывает на текущий каталог. Например, Get-ChildItem . позволяет просмотреть содержимое текущего местоположения.
  • Две точки .. указывают на родительский каталог. Например, Set-Location .. позволяет перейти к родительскому каталогу. Это может быть полезно, если вы находитесь в глубоко вложенной директории.

Большинство командлетов имеют параметры -Path и -LiteralPath, позволяющие указать путь к файлу или папке. Разница между ними заключается в том, что в -Path можно включать переменные, в то время как —LiteralPath интерпретирует символы буквально, даже если они содержат имя переменной.

Get-Help: как изучать новые командлеты

Для получения подробной информации о конкретном командлете воспользуйтесь командой Get-Help Название-Командлета. Пример:

Get-Help Get-Childitem
Get-Help получить информацию о командлете get-childitem в powershell

У команды Get-Help имеется несколько полезных параметров:

  • -Detailed предоставляет более подробную справку по командлету.
  • -Full предоставляет полную справку.
  • -Examples демонстрирует примеры использования командлета.
  • -Online перенаправляет пользователя на веб-страницу с соответствующей документацией.

Чем PowerShell отличается от cmd

Рассмотрим сравнение двух основных инструментов командной строки в операционной системе Windows: PowerShell и командной строки (cmd). Оба инструмента позволяют взаимодействовать с операционной системой через команды и сценарии, однако они существенно различаются по своим характеристикам и функциональности.

АспектPowerShellКомандная строка (cmd)
Язык сценариевМощный язык на основе .NET FrameworkОграниченный язык для выполнения команд
Объектная модельРабота с объектами и конвейерная обработкаРабота с текстовыми строками и потоками
Управление системойОбширный набор командлетов для управленияОграниченный набор команд для управления
СинтаксисСовременный и читаемый синтаксисПростой синтаксис команд и аргументов
Поддержка модулейПоддержка модулей для организации функциональностиОтсутствие концепции модулей
Таблица сравнения PowerShell и cmd.

Логические операторы

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

  • + — сложение;
  • - — вычитание;
  • * — умножение;
  • / — деление;
  • % — деление по модулю;
  • ( и ) — скобки для группировки операций.

Операторы сравнения оформляются так же, как параметры командлетов, и их названия произошли от английских выражений, указанных в скобках:

  • -eq — равно (от «equal»);
  • -ne — не равно (от «not equal»);
  • -gt — больше (от «greater than»);
  • -ge — больше либо равно (от «greater than or equal»);
  • -lt — меньше (от «less than»);
  • -le — меньше либо равно (от «less than or equal»).

Для чего нужен PowerShell

PowerShell — это мощный инструмент для автоматизации задач, управления операционной системой и взаимодействия с различными приложениями и сервисами. Он широко используется администраторами систем, разработчиками, а также специалистами в области IT для решения разнообразных задач. Вот некоторые из основных применений PowerShell:

  1. Автоматизация задач: PowerShell позволяет создавать сценарии (скрипты) для автоматизации повторяющихся и рутинных задач, таких как установка программ, настройка системных параметров, копирование файлов и многие другие операции.
  2. Управление системой: PowerShell предоставляет доступ к широкому спектру системных функций, позволяя администраторам управлять пользователями, группами, службами, процессами, реестром и другими системными ресурсами.
  3. Конфигурация и развертывание: С помощью PowerShell можно создавать и применять конфигурации для развертывания и управления серверами и компьютерами, что делает процесс управления парком устройств более эффективным.
  4. Мониторинг и анализ: PowerShell позволяет анализировать системные данные, собирать статистику, мониторить производительность и события, что помогает администраторам быстро реагировать на проблемы.
  5. Взаимодействие с внешними приложениями и службами: PowerShell может взаимодействовать с другими приложениями и службами, используя API, веб-службы, REST API и другие протоколы, что позволяет автоматизировать процессы, связанные с сторонними приложениями.
  6. Разработка и тестирование: Разработчики используют PowerShell для создания сценариев тестирования, сборки проектов, управления версиями и других задач, связанных с разработкой ПО.
  7. Обработка данных: PowerShell предоставляет мощные инструменты для обработки и анализа данных, таких как текстовые файлы, CSV, XML и другие форматы данных.
  8. Безопасность: PowerShell может использоваться для управления политиками безопасности, мониторинга событий безопасности, а также для проведения аудитов безопасности системы.

Как открыть PowerShell в Windows

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

:/>  Почему стоит выбрать «Дата-Хата»

PowerShell является независимым от версии операционной системы инструментом и работает одинаково стабильно как на Windows 10, так и на Windows Server.

Существует два основных метода для запуска PowerShell или PowerShell ISE в системе Windows: через меню «Пуск» и с помощью приложения «Выполнить».

  • Для того чтобы открыть PowerShell через меню «Пуск», пройдите к папке Windows PowerShell, откройте её и выберите необходимое приложение. В этой директории доступны как 32-разрядные версии (отмечены как x86 в скобках), так и 64-разрядные версии терминала и ISE.
открыть PowerShell можно через Пуск
  • Чтобы запустить PowerShell через приложение «Выполнить», используйте комбинацию клавиш Win + R. Когда появится окно, введите powershell или powershell ise (в зависимости от того, какое приложение вам нужно) и нажмите кнопку ОК.
открытие PowerShell через команду выполнить

Где может пригодиться IM?

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

– Накладывать водяные знаки

– Делать что-нибудь черно-белым

– Делать из одной картинки несколько, но в разных размерах

– Сделать машину по производству смешных картинок для канала в Телеграм

Последнее, конечно же, шутка

Чтение и запись данных в excel файл из power shell

На самом деле, те примеры, которые я буду приводить дальше – это часть pet-проекта собственной системы управления контентом для группы ВК и Телеграм канала, которая зашла слишком далеко. Едва ли вам понадобится нечто подобное, но вариации команд, описанные там, без проблем покроют операции работы с картинками из карточек номенклатуры, например.

Задача 6

Запустить все файлы в папке оказалось легко средствами PowerShell. Как я уже упоминал ранее, запускаем его от имени администратора в папке, где лежит output от задачи 5. У меня это c:\speech_sense\upload_data\calls\powershell\

Set-ExecutionPolicy RemoteSigned

Get-ChildItem -Path . -Filter "*.ps1" | ForEach-Object { powershell -File $_.FullName }

Все файлы подгрузились примерно за ночь. Стоимость обработки составила примерно рубль на один фрагмент. В проекте с аудиофайлами перед загрузкой необходимо создать тег, в котором ищем фразы поздравления с праздником. Обязательно перед загрузкой файлов. Новые и отредактированные теги на уже загруженные файлы не работают. Хотите новый тег создать и посмотреть, где он встречается – грузите и платите за расшифровку заново.

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

Работа со строками в PowerShell

PowerShell — мощный инструмент для автоматизации задач на платформе Windows. Работа со строками играет важную роль при обработке текстовых данных. Вот некоторые ключевые аспекты:

  1. Объединение строк: Чтобы объединить строки, используйте оператор + или метод .Concat(). Пример:
$firstString = "Привет, "
$secondString = "мир!"
$combinedString = $firstString + $secondString
  1. Форматирование строк: Используйте оператор -f или метод .Format() для вставки значений в строку. Пример:
$name = "Alice"
$age = 30
$formattedString = "Привет, меня зовут {0} и мне {1} лет." -f $name, $age
  1. Интерполяция строк: С помощью символа $ и фигурных скобок {} можно вставлять значения переменных в строки. Пример:
$city = "Москва"
$interpolatedString = "Я живу в городе $($city)."
  1. Разделение строк: Метод .Split() используется для разделения строки на подстроки. Пример:
$text = "яблоко,груша,банан"
$fruits = $text.Split(",")
  1. Замена подстрок: С помощью метода .Replace() можно заменить подстроку в строке. Пример:
$text = "Привет, мир!"
$modifiedText = $text.Replace("мир", "вселенная")
  1. Обрезка строк: Методы .Trim(), .TrimStart() и .TrimEnd() удаляют пробелы и другие символы в начале и конце строки.

Примеры использования методов для обрезки строк в PowerShell:

# Обрезка пробелов в начале и конце строки
$rawString = "   Пример строки с пробелами   "
$trimmedString = $rawString.Trim()
Write-Host "Исходная строка: '$rawString'"
Write-Host "Обрезанная строка: '$trimmedString'"

# Обрезка только в начале строки
$leftTrimmedString = $rawString.TrimStart()
Write-Host "Строка после обрезки в начале: '$leftTrimmedString'"

# Обрезка только в конце строки
$rightTrimmedString = $rawString.TrimEnd()
Write-Host "Строка после обрезки в конце: '$rightTrimmedString'"

При выполнении этого кода в консоли PowerShell вы увидите следующий вывод:

Исходная строка: '   Пример строки с пробелами   '
Обрезанная строка: 'Пример строки с пробелами'
Строка после обрезки в начале: 'Пример строки с пробелами   '
Строка после обрезки в конце: '   Пример строки с пробелами'

В данном примере видно, как методы .Trim(), .TrimStart() и .TrimEnd() удаляют пробелы в начале и конце строки, соответственно.

Доступ к данным в файле Excel из PowerShell

Рассмотрим на простом примере как получить доступ из PowerShell к данным в Excel файле со списком сотрудников.

excel файл с данными, как прочитать из powershell скрипта

Запустите приложение Excel (Application layer), создав COM объект:

Чтобы создать этот COM объект, Excel должен быть установлен на компьютере.

Эта команда запустите в фоновом режиме приложение Excel. Чтобы сделать окно Excel видимым, нужно изменить свойство Visible COM объекта:

Вывести все свойства объекта Excel:

Теперь можно открыть файл Excel (книгу, workbook):

отрыть excel файл с помощью powershell

В каждом файле Excel может быть несколько листов (worksheets). Вывести список листов в текущей книге Excel:

Теперь можно открыть конкретный лист (по его имени или индексу):<

Текущий (активный) лист Excel можно узнать командой:

выбрать активную книгу excel с помощью powershell

Для получения значения из ячейки Excel нужно указать ее номер. Теперь вы можете получить значения из ячеек документа Excel. Можно использовать различные способы адресации ячеек в книге Excel: через диапазон (Range), ячейку (Cell), столбец (Columns) или строку (Rows). Ниже показаны примеры получения данных из одной и той же ячейки:

powershell - получить значение ячейки excel

Переменные

Для сохранения данных и обращения к ним в будущем в PowerShell используются переменные. Перед названием переменной ставится символ доллара $, и переменные могут содержать латинские буквы (как заглавные, так и строчные), цифры и символ нижнего подчеркивания.

Переменные в могут хранить данные различных типов, и значения в них можно изменять (перезаписывать).

объявление переменной и ее вызов в powershell ise

Создадим переменную со строкой 2023 и преобразуем её в число. Для того чтобы узнать тип данных, воспользуемся методом .GetType():

$stringValue = "2023"
$intValue = [int]$stringValue
$intValue.GetType()
определение переменной в powershell

Для удаления переменной используется метод .Clear().

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

$number = 42
Write-Host "The number is $number"   # Вывод: The number is 42
Write-Host 'The number is $number'   # Вывод: The number is $number

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

Кроме пользовательских переменных, существуют и системные переменные. Например, $PSVersionTable содержит информацию о версии PowerShell.

узнать версию powershell с помощью системной переменной PSVersionTable

Очистка журнал событий из графической консоли Event Viewer

Самый интуитивный способ очистки журналов событий Windows – воспользоваться графической консоль Event Viewer.

  1. Запустите консоль
    eventvwr.msc
    ;Очистка журналов из консоли просмотра событий
  2. Щелкните правой кнопкой по журналу и выберите Clear Log;

Такой способ позволяет быстро удалить все события из одного конкретного журнала. Однако в Windows используется несколько сотен журналов для разных компонентов операционной системы и стороннего ПО.

По умолчанию Windows хранит журналы в файлах с расширением EVTX в каталоге
%SystemRoot%\System32\Winevt\Logs\
.

Каталог System32\Winevt\Logs с EVTX логами WIndows

Если вам нужно очистить их все – это будет утомительно вручную прощелкать все разделы Event Viewer и очистить каждый журнал. В этом случае для удаления событий лучше использовать PowerShell или командную строку.

Циклы

В PowerShell существует несколько видов циклов:

  • Цикл с предусловием while:
$counter = 0

while ($counter -lt 5) {
    Write-Host "Counter is $($counter)"
    $counter++
}
  • Цикл с постусловием истинным do while:
$counter = 0

do {
    Write-Host "Counter is $($counter)"
    $counter++
} while ($counter -lt 5)
  • Цикл с постусловием ложным do until:
$counter = 0

do {
    Write-Host "Counter is $($counter)"
    $counter++
} until ($counter -ge 5)
  • Цикл с известным числом итераций for:
for ($i = 0; $i -lt 5; $i++) {
    Write-Host "Iteration is $i"
}
  • Цикл с перебором элементов коллекции foreach:
$numbers = 1..5

foreach ($num in $numbers) {
    Write-Host "Number is $num"
}

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

Условия

Условные операторы в PowerShell создаются с использованием ключевых слов if, elseif и else. В круглых скобках указывается само условие, а в фигурных скобках содержится код, который выполняется при выполнении условия. Например:

$Number = 123

if ($Number -gt 0) {
    Write-Host 'Число больше нуля'
} elseif ($Number -lt 0) {
    Write-Host 'Число меньше нуля'
} else {
    Write-Host 'Число равно нулю'
}

Результат выполнения кода: Число больше нуля

Кроме того, условия также можно задавать с помощью ключевого слова switch. Например:

$Day = 5

switch ($Day) {
    1 { Write-Host 'Понедельник' }
    2 { Write-Host 'Вторник' }
    3 { Write-Host 'Среда' }
    4 { Write-Host 'Четверг' }
    5 { Write-Host 'Пятница' }
    6 { Write-Host 'Суббота' }
    7 { Write-Host 'Воскресенье' }
}

Результат выполнения кода: Пятница

Задача 3

Внезапно оказалось, что грузить и анализировать все аудиозаписи полностью очень дорого, такого бюджета у проекта не было. Быстро прослушав какие-то части и прогнав несколько сотен через бесплатные или десктопные STT решения, я обнаружил, что поздравления встречаются только в конце аудиофайла. Появилась идея отрезать только последние 30 секунд и проанализировать их. Установив в python модуль ffmpeg и прописав в windows PATH путь к кодеку удалось решить задачу вот так:

import os
import ffmpeg
from pydub import AudioSegment

mp3_folder = 'c:\\speech_sense\\upload_data\\calls\\'
wave_folder = 'c:\\speech_sense\\upload_data\\calls\\wave\\'
finish_fragment_folder = 'c:\\speech_sense\\upload_data\\calls\\wave\\finish_fragment\\'

def convert_mp3_to_wav(mp3_path, wav_path):
    """
    Конвертируем MP3 в WAV используя модуль и установленный кодек ffmpeg.
    """
    try:
        ffmpeg.input(mp3_path).output(wav_path).run()
        print(f"Converted {mp3_path} to {wav_path}")
    except Exception as e:
        print(f"Error converting {mp3_path} to WAV: {e}")

def extract_last_30_seconds(wav_path, output_path):
    """
    Извлекаем последние 30 секунд в WAV файле.
    """
    try:
        audio = AudioSegment.from_wav(wav_path)
        last_30_seconds = audio[-30000:]  # оставляем последние 30000 мс (30 секунд)
        last_30_seconds.export(output_path, format="wav")
        print(f"Extracted last 30 seconds to {output_path}")
    except Exception as e:
        print(f"Error extracting last 30 seconds from {wav_path}: {e}")

if __name__ == "__main__":

    # перебираем все файлы и конвертируем.
    for filename in os.listdir(mp3_folder):
        if filename.endswith('.mp3'):
            mp3_file = os.path.join(mp3_folder, filename)
            wave_filename = f"{os.path.splitext(filename)[0]}.wav"
            wav_file = os.path.join(wave_folder, wave_filename)
            finish_fragment_filename = f"{os.path.splitext(filename)[0]}_last_30_seconds.wav"
            output_last_30_seconds = os.path.join(finish_fragment_folder, finish_fragment_filename)
    
            # Если Вам, уважаемый читатель, кажется, что решение Задачи 1 не подходит,
            # Просто сотрите символ комментария со стороки внизу.
            # Функция convert_mp3_to_wav() решает задачу 1 средствами python
            # convert_mp3_to_wav(mp3_file, wav_file)
            
            extract_last_30_seconds(wav_file, output_last_30_seconds)

На calls\wave\finish_fragment\ повторно пришлось прогнать скрипт из Задачи 2 и получить метаданные уже по обрезанным фрагментам.

:/>  Power shell и selenium проще чем кажется

Задача 5

Начальные условия задачи были такие:

  • У меня есть 25000 готовых к загрузке аудиофайлов.

  • К каждому аудиофайлу созданы метаданные в .json с таким-же названием.

  • Примера с пакетной загрузкой в документации Яндекса нет.

  • Грузить файлы я умею только по одному.

  • Если прописать команду загрузки файла (см. первую часть статьи) в файл PowerShell .ps1 и запустить – ничего, кроме сообщения, что команду выполнить нельзя, не происходит.

Проблему с запуском файлов .ps1 я решил вот так: (https://ru.stackoverflow.com/questions/935212/powershell-выполнение-сценариев-отключено-в-этой-системе)

Открываем терминал с правами администратора
Пишем и запускаем: Set-ExecutionPolicy RemoteSigned
На вопрос отвечаем: A (Да для всех)

Далее я создал каждому аудиофайлу свой файл .ps1 для загрузки в SpeechSense.

import os

wave_directory = 'c:\\speech_sense\\upload_data\\calls\\wave\\finish_fragment\\'
output_directory = 'c:\\speech_sense\\upload_data\\calls\\powershell\\'
# Constants for connection ID and key
CONNECTION_ID = 'ID подключения' # Замените на свой
KEY = 'API_KEY'  # Замените на свой

def generate_powershell_script(audio_filename):
    # Определяем имя файла для метаданных в .json взяв исходное имя файла без расширения
    base_name = os.path.splitext(audio_filename)[0]
    json_filename = f"{base_name}.json"

    # пишем команду PowerShell которая нужна для загрузки
    # обратите внимание, где стоят кавычки "". Без них .ps1 ничего не запускал
    cmd = f'py upload_grpc.py --audio-path "{wave_directory}\\{audio_filename}" --meta-path "{wave_directory}\\{json_filename}" --connection-id {CONNECTION_ID} --key {KEY}'
    
    # Имя скрипта PowerShell
    ps_script_filename = f"{base_name}.ps1"
    
    # Пишем команду в файл PowerShell
    with open(os.path.join(output_directory, ps_script_filename), 'w') as ps_script_file:
        ps_script_file.write(cmd)   
    
    print(f"Generated {ps_script_filename}")

def main():
    # Проверяем, существует ли основная директория
    if not os.path.isdir(wave_directory):
        print(f"The directory {wave_directory} does not exist.")
        return
    
    # Формируем скрипт PowerShell для каждого файла .wav в директории
    for filename in os.listdir(wave_directory):
        if filename.endswith('.wav'):
            generate_powershell_script(filename)

if __name__ == '__main__':
    main()

Задача 4

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

Сразу признаюсь, что с автоматизацией этой задачи я не справился. Python молча и напрочь отказался создавать список директорий. Падал с ошибкой в строке 6. Причин такого поведения я обнаружить или нагуглить не смог. Подозреваю, что дело в пробелах, русских буквах в названиях директорий или в том, что файлы лежат на сетевых дисках.

Код решения я всё равно выложу, возможно кто-то увидит, объяснит и поправит ошибки. Буду благодарен.

import os
import shutil
import glob

# список directories и переменную directories_list python отказывался создавать
directories = ['/path/to/dir1', '/path/to/dir2', '/path/to/dir3']
directories_list = '/path/to/dir3'
destination_dir = 'c:\\speech_sense\\upload_data\\calls\\'
        
os.makedirs(destination_dir, exist_ok=True)

def copy_mp3_files(directories, destination):
    for directory in directories:
        
        mp3_files = glob.glob(os.path.join(directory, '*.mp3'))
        
        for mp3 in mp3_files:
            
            shutil.copy(mp3, destination)


copy_mp3_files(directories, destination_dir)

Задача 2

Для подгрузки аудиозаписи в SpeechSense желательно иметь файл с метаданными аудиозаписи. Инструкция предлагает 2 варианта, создать .json файл к каждому аудио самостоятельно, либо, при отсутствии файла, использовать всегда вот такой формат:

now = datetime.datetime.now().isoformat()
metadata = {
         'operator_name': 'Operator',
         'operator_id': '1111',
         'client_name': 'Client',
         'client_id': '2222',
         'date': str(now),
         'date_from': '2023-09-13T17:30:00.000',
         'date_to': '2023-09-13T17:31:00.000',
         'direction_outgoing': 'true',
      }

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

В первом случае в имени файла был только ID звонка.

import os
import json
from datetime import datetime

# Папка с файлами в формате wave из предыдущего скрипта.
wave_folder = 'c:\\speech_sense\\upload_data\\calls\\wave\\'

# Получение текущей даты в формате YYYY-MM-DDTHH:MM:SS.SSS. 
# Яндекс требует все даты именно в таком формате, пришлось повозиться, чтобы
# отформатировать время корректно. При любых отклонениях от этого формата  
# загрузка аудио в SpeechSense заканчивается ошибкой.
current_date = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]

# Проходим по всем файлам в папке
for filename in os.listdir(wave_folder):
    if filename.endswith('.wav'):
        # Создание шаблона JSON для каждого файла
        data = {
            "operator_name": os.path.splitext(filename)[0],
            "operator_id": os.path.splitext(filename)[0],
            "client_name": "Client",
            "client_id": "1",
            "date": current_date,
            "direction_outgoing": "true",
            "language": "ru"
        }
        # Для имени и ID оператора используем ID из названия файла.
        # По этому ID можно будет узнать, в каком файле найдены поздравления.
        # Имя JSON файла
        json_filename = f"{os.path.splitext(filename)[0]}.json"

        # Запись данных в JSON файл. Обязательно указывать кодировку windows-1251
        # без параметра или в UTF-8 SpeechSense преобразует все русские буквы в кракозябры.
        with open(os.path.join(wave_folder, json_filename), 'w', encoding='windows-1251') as json_file:
            json.dump(data, json_file, ensure_ascii=False, indent=4)

print("JSON файлы успешно созданы.")

Во втором случае в имени файла была информация о дате и времени звонка, контактном телефоне клиента и ID звонка. Шаблон имени файла был такой “YYYYMMDD-HHMM-toXXXXXXXXXX-ID.wav”. Решение выглядит вот так

import os
import json
from datetime import datetime

# Папка с файлами
wave_folder = 'c:\\speech_sense\\upload_data\\calls\\wave\\'


for filename in os.listdir(wave_folder):
    if filename.endswith('.wav'):
        # разбиваем имя файла по разделителю "-"
        data = os.path.splitext(filename)[0]
        parts = data.split("-")
        # склеиваем первую и вторую часть имени, где остаются дата и время звонка.
        date_str = parts[0] + parts[1]
        # приводим к необходимому для SpeechSense формату даты
        date_object = datetime.strptime(date_str, "%Y%m%d%H%M")
        formatted_date = date_object.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
        
        data = {
            "operator_name": "Operator",
            "operator_id": parts[3],
            "client_name": "Respondent",
            "client_id": parts[2],
            "date": formatted_date,
            "direction_outgoing": "true",
            "language": "ru"
        }

        # пишем JSON файл, не забыв указать кодировку.
        json_filename = f"{os.path.splitext(filename)[0]}.json"
        
        with open(os.path.join(wave_folder, json_filename), 'w', encoding='windows-1251') as json_file:
            json.dump(data, json_file, ensure_ascii=False, indent=4)

print("JSON файлы успешно созданы.")

Я понимаю, что тут найдутся специалисты, которые справедливо упрекнут, что нарушен принцип DRY, код повторяется и при желании не сложно написать одну функцию, которая будет извлекать метаданные из имен файла любого формата. Да, всё верно, рефакторинг кода уже запланирован на будущее. А тут изначально и планировались и проект по документации должен хранить в именах файлов только ID. Реальность оказалась сложнее. Вторая часть задачи возникла совершенно внезапно, когда весь код уже был написан.

Как получить данные из Active Directory и сохранить их в книге Excel?

Рассмотрим практический пример как можно использовать PowerShell для получения данных из Excel. Например, вы хотите получить для каждого пользователя в Excel файле получить информацию из Active Directory. Например, его телефон (атрибут telephoneNumber), отдел (department) и email адрес (mail).

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

powershell скрипт для получения данных пользователей из Active Directory и сохранения в Excel

Рассмотрим еще один пример построения отчета с помощью PowerShell и Excel. Допустим, вам нужно построить Excel отчет о состоянии службы Print Spooler на всех серверах домена.

  • Вы можете поручить сотруднику отдела кадров вести реестр пользователей в Excel, а затем с помощью PowerShellс скриптов создавать новых пользователей в AD (New-ADUser) или обновлять их данные (Set-ADUser). Можно делегировать этому пользователю права на изменение этих атрибутов.
  • Пример скрипта PowerShell для рассылки писем из Outlook по списку пользователям из Excel файла.

Работа с файлами

PowerShell предоставляет удобные средства для работы с файлами. Вот некоторые ключевые методы:

Для создания файла используйте командлет New-Item с указанием пути к файлу:

New-Item -Path "C:\путь\к\файлу\новыйфайл.txt" -ItemType File

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

"Содержимое файла" | Out-File -FilePath "C:\путь\к\файлу\новыйфайл.txt"
Set-Content -Path "C:\путь\к\файлу\новыйфайл.txt" -Value "Новое содержимое файла"

Для чтения содержимого файла в массив используйте Get-Content:

$содержимое = Get-Content -Path "C:\путь\к\файлу\новыйфайл.txt"

Для получения информации о файле (размер, дата создания и др.) используйте Get-Item:

$информацияОФайле = Get-Item -Path "C:\путь\к\файлу\новыйфайл.txt"

Для копирования файла в другое место используйте Copy-Item:

Copy-Item -Path "C:\путь\к\файлу\новыйфайл.txt" -Destination "C:\путь\к\копия\новыйфайл.txt"

Для удаления файла воспользуйтесь командлетом Remove-Item:

Remove-Item -Path "C:\путь\к\файлу\новыйфайл.txt" -Force

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

Записать значение в ячейку Excel из PowerShell

Вы можете изменить значение любой ячейки в книге Excel. Например, вы хотите изменить должность пользователя в файле.

Получить текущее значение ячейки:

Присвойте новое значение ячейке:

$ExcelWorkSheet.cells.Item(2, 3) = 'Начальник отдела продаж'

powershell: изменить значение в ячейке excel

Изменить размер шрифта и выделить новое значение жирным:

$ExcelWorkSheet.cells.Item(2, 3).Font.Bold = $true
$ExcelWorkSheet.cells.Item(2, 3).Font.size=14

Сохранить изменения и закрыть книгу Excel:

Закрыть приложение Excel:

Изменить шрифт в ячейке excel из powershell

Откройте XLSX файл и проверьте, что данные и шрифт в указанной ячейки были изменены.

Если вам нужно создать новый лист в документе Excel:

$ExcelWorkSheet = $ExcelWorkBook.Worksheets.Add()
$ExcelWorkSheet.Name = "NewSheet"

Удалить целиком столбец или строку:

$ExcelWorkSheet.cells.Item(5, 1).EntireRow.Delete()
$ExcelWorkSheet.cells.Item(2, 1).EntireColumn.Delete()

Работа в PowerShell ISE

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

Интерфейс среды разработки скриптов PowerShell ISE

PowerShell ISE представляет собой инструмент, состоящий из трех основных панелей:

  • Область скриптов в верхней части экрана, предназначенная для написания сценариев.
  • Консольная область в нижней части экрана, которая функционирует как обычный терминал, позволяя вводить команды в интерактивном режиме.
  • Панель команд в правой части экрана, предоставляющая полное руководство по командам PowerShell. В ней также есть конструктор, который помогает задать значения нужных параметров.
:/>  Как открыть конфигурацию системы windows 10. Команда msconfig (Windows 10): как зайти в настройки конфигурации системы

Комментарии в коде

Вот пример PowerShell скрипта с комментариями:

# Это комментарий в одну строку, начинается с символа '#' и продолжается до конца строки.

# Пример переменной
$имя = "John"
$возраст = 30

# Вывод информации
Write-Host "Привет, $имя! Тебе $возраст лет."

# Это многострочный комментарий, который начинается с '<#' и заканчивается '#>'.
<#
Этот блок комментария может быть многострочным и располагаться
на нескольких строках, чтобы объяснить более сложные участки кода.
#>

# Функция для сложения двух чисел
function Сложить-Числа {
    param(
        [int]$число1,
        [int]$число2
    )

    $результат = $число1 + $число2

    return $результат
}

# Вызов функции и вывод результата
$результатСложения = Сложить-Числа -число1 5 -число2 7
Write-Host "Результат сложения: $результатСложения"

Хорошая практика — комментировать код таким образом, чтобы другие разработчики (или вы в будущем) могли легко понять, как работает код и какие цели преследовались при его написании.

Советы по написанию хорошего кода:

  • Применяйте нотацию PascalCase для названий командлетов, функций, параметров, свойств, методов, переменных и классов. Разработчики Powershell выпустили для этого гайд. Не рекомендуется: get-service, Get-service, GET-SERVICE. Рекомендуется: Get-Service.
  • Используйте полные названия командлетов. Алиасы удобны для интерактивного режима, но в скриптах они могут затруднить понимание. Не рекомендуется: dir, gci, ls. Рекомендуется: Get-ChildItem.
  • Применяйте стиль One True Brace для форматирования вложенных блоков кода. Если вы используете фигурные скобки, внутренний код отделяется табуляцией (четыре пробела), а фигурные скобки размещаются следующим образом:
if ($var1 -eq $var2) {
    # Код внутри условия
} else {
    # Код внутри else
    # Еще код внутри else
}

Исключение: когда код внутри фигурных скобок небольшой, его можно записать в одну строку:

Get-ChildItem | Where-Object { $_.Length -gt 10mb }

Запуск скриптов

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

Также существует возможность запуска скрипта из оболочки. Например, предположим, у вас есть файл скрипта test_script.ps1 в каталоге C:\Scripts. Вы можете выполнить его двумя способами:

  1. Используя команду PowerShell -File C:\Scripts\test_script.ps1 из любого места. Это позволяет запустить скрипт, указав полный путь к файлу.
  2. Используя команду .\test_script.ps1, если вы находитесь в каталоге C:\Scripts. Это запустит скрипт, находясь в том же каталоге, что и файл скрипта.

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

Политика выполнения. Как разрешить выполнения скриптов

По умолчанию запрещено выполнение файлов с PowerShell-скриптами, и это сделано с целью обеспечения безопасности. Вы можете узнать текущую политику выполнения с помощью командлета Get-ExecutionPolicy. Вот какие варианты политики выполнения могут быть доступны:

  • Restricted (Установлена по умолчанию) — запрещено выполнение любых скриптов. Это означает, что нельзя будет запустить ни один скрипт.
  • AllSigned — разрешено выполнение только тех скриптов, которые были подписаны доверенным разработчиком. Это обеспечивает повышенный уровень безопасности, так как только подписанные и проверенные скрипты могут быть выполнены.
  • RemoteSigned — разрешено выполнение подписанных доверенным разработчиком скриптов, а также собственных скриптов. Это предоставляет баланс между безопасностью и удобством, позволяя запускать свои скрипты.
  • Unrestricted — разрешено выполнение любых скриптов без каких-либо ограничений. Это предоставляет наивысший уровень гибкости, но может повысить риск безопасности.

Чтобы ваши файлы с расширением .ps1 запускались, вам следует изменить политику выполнения на RemoteSigned. Для этого выполните следующие шаги:

  • Откройте PowerShell от имени администратора. Для этого щелкните правой кнопкой мыши по значку PowerShell на панели задач или в меню «Пуск» и выберите «Запуск от имени администратора».
  • В открывшемся окне PowerShell введите следующую команду и нажмите Enter:
Set-ExecutionPolicy RemoteSigned
  • Подтвердите изменение политики выполнения, нажав клавишу Y (Yes).

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

Удаление логов Windows из командной строки

Для очистки журналов Windows из командной строки используется утилита wevtutil.exe.

Вывести список зарегистрированных в Windows журналов событий:

или короткий вариант:

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

WevtUtil cl Microsoft-Windows-GroupPolicy/Operational

Перед очисткой можно создать резервную копию событий в журнале в отдельный файл:

WevtUtil cl Microsoft-Windows-GroupPolicy/Operational /bu:GPOLOG_Bak.evtx

Можно очистить сразу все журналы событий из cmd.exe:

for /F "tokens=*" %1 in ('wevtutil.exe el') DO wevtutil.exe cl "%1"

Для BAT файла нужно использовать немного другой синтаксис:

for /F "tokens=*" %%1 in ('wevtutil.exe el') DO wevtutil.exe cl "%%1"

Еще несколько вариантов скриптов

1. Рекламка книги из онлайн библиотеки 

Чтение и запись данных в excel файл из power shell

convert -resize 365x528! book1.png book1.png
convert "book1.png"   +clone  -background black  -shadow 80x3+5+5  +swap -background none   -layers merge  +repage    shadow.png

magick bookpattern.png shadow.png -geometry +125+510 -composite book.png
magick book.png book1.png -geometry +120+500 -composite book.png

magick book.png bookframe.png -geometry +120+500 -composite book.png
magick book.png -pointsize 32 -fill white -font Sylfaen -gravity South -annotate -210+120 'Королева Марго' book.png
magick book.png -pointsize 22 -fill grey -font Tahoma -gravity South -annotate -210+90 'Александр Дюма' book.png
magick book.png -pointsize 88 -fill white -font Sylfaen -gravity Center -annotate +0-290 'Королева Марго' book.png
magick book.png -pointsize 24 -fill grey -font Tahoma -gravity Center -annotate +0-220 'Александр Дюма в библиотеке Two-Digit Athenaeum'book.png
magick book.png -pointsize 66 -fill grey -font Sylfaen -gravity South -annotate +160+330 'по коду:' book.png
magick book.png -pointsize 120 -fill white -font Tahoma -gravity South -annotate +200+195 '9VAN2' book.png
convert -resize 768x768 book.png book.png

P.S. Из нового – строки 2 и 3. В строке 2 создается png тени от book1.png, а в 3 – тень накладывается на фон. На фоне уже есть темное пятно, да, но тень из скрипта тоже рабочая.

Функция СформироватьРекламуКниги(Знач Книга) Экспорт
	
	ФонДД 	= Справочники.Файлы.РК_Фон.Файл.Получить();
	Фон		= ПолучитьИмяВременногоФайла(".png");
	ФонДД.Записать(Фон);
	
	РамкаДД = Справочники.Файлы.РК_Рамка.Файл.Получить();
	Рамка	= ПолучитьИмяВременногоФайла(".png");
	РамкаДД.Записать(Рамка);
	
	ОбъектКнига = Книга.ПолучитьОбъект();
	
	КартинкаКнигиДД = ОбъектКнига.КартинкаДвоичные.Получить();
	КартинкаКниги 	= ПолучитьИмяВременногоФайла(".png");
	КартинкаКнигиДД.Записать(КартинкаКниги);
	
	КодКниги 		= ОбъектКнига.Код;
	НазваниеКниги 	= ОбъектКнига.Наименование;
	АвторКниги 		= ОбъектКнига.Автор.Имя + " " + ОбъектКнига.Автор.Фамилия;
	
	КартинкаОбработанная = ПолучитьИмяВременногоФайла(".png");
	
	МассивВФ = Новый Массив;
	МассивВФ.Добавить(Фон);
	МассивВФ.Добавить(Рамка);
	МассивВФ.Добавить(КартинкаКниги);
	
	
	ИмяСкрипта				= ПолучитьИмяВременногоФайла(".ps1");
	ТекстСкрипта			= Новый ТекстовыйДокумент();
	ТекстСкрипта.УстановитьТекст(
	
	"convert -resize 365x528! """
	+ КартинкаКниги
	+ """ """
	+ КартинкаКниги
	+ """"
	+ Символы.ПС
	+ "magick """
	+ Фон
	+ """ """
	+ КартинкаКниги
	+ """ -geometry +120+500 -composite """
	+ КартинкаОбработанная
	+ """"
	+ Символы.ПС
	+ "magick """
	+ КартинкаОбработанная
	+ """ """
	+ Рамка
	+ """ -geometry +120+500 -composite """
	+ КартинкаОбработанная
	+ """"
	+ Символы.ПС
	+ "magick """
	+ КартинкаОбработанная
	+ """ -pointsize 32 -fill white -font Sylfaen -gravity South -annotate -210+120 '"
	+ НазваниеКниги
	+ "' """
	+ КартинкаОбработанная
	+ """"
	+ Символы.ПС
	+ "magick """
	+ КартинкаОбработанная
	+ """ -pointsize 22 -fill grey -font Tahoma -gravity South -annotate -210+90 '"
	+ АвторКниги
	+ "' """
	+ КартинкаОбработанная
	+ """"
	+ Символы.ПС
	+ "magick """
	+ КартинкаОбработанная
	+ """ -pointsize 88 -fill white -font Sylfaen -gravity Center -annotate +0-290 '"
	+ НазваниеКниги
	+ "' """
	+ КартинкаОбработанная
	+ """"
	+ Символы.ПС
	+ "magick """
	+ КартинкаОбработанная
	+ """ -pointsize 24 -fill grey -font Tahoma -gravity Center -annotate +0-220 '"
	+ АвторКниги
	+ " в библиотеке Two-Digit Athenaeum'"""
	+ КартинкаОбработанная
	+ """"
	+ Символы.ПС
	+ "magick """
	+ КартинкаОбработанная
	+ """ -pointsize 66 -fill grey -font Sylfaen -gravity South -annotate +160+330 'по коду:' """
	+ КартинкаОбработанная 
	+ """"
	+ Символы.ПС
	+ "magick """
	+ КартинкаОбработанная
	+ """ -pointsize 120 -fill white -font Tahoma -gravity South -annotate +200+195 '"
	+ КодКниги
	+ "' """
	+ КартинкаОбработанная
	+ """"
	+ Символы.ПС
	+ "convert -resize 768x768 """
	+ КартинкаОбработанная
	+ """ """
	+ КартинкаОбработанная
	+ """"

	
	);
	
	ТекстСкрипта.Записать(ИмяСкрипта, КодировкаТекста.UTF8);

	КодВозврата = 0;
	ЗапуститьПриложение("powershell -file " + ИмяСкрипта, ,Истина, КодВозврата);
	
	УдалитьФайлы(ИмяСкрипта);
	
	СтруктураВозврата = Новый Структура;
	СтруктураВозврата.Вставить("Картинка", КартинкаОбработанная);
	СтруктураВозврата.Вставить("МассивВФ", МассивВФ);
	
	Возврат СтруктураВозврата
	
КонецФункции

2. Создание карточек разного размера по пути к файлу

Сразу перейду к 1С. Ничего сложного этот код не делает: берет путь к файлу из параметра и обходит соответствие, где ключ – имя файла, а значение – размер. Сохраняется все в webp рядом с основной картинкой 

Процедура СоздатьКарточки(Знач ПутьКОригиналу) Экспорт
	
	Картинка 		= Новый Файл(ПутьКОригиналу);
	Путь			= Картинка.Путь;
	Размеры 		= Новый Соответствие;
	
	Размеры.Вставить("small"	, "175x270");
	Размеры.Вставить("medium"	, "295x455");
	
	Для Каждого Размер Из Размеры Цикл
		
		РазмерМассив = СтрРазделить(Размер.Значение, "x");
		Ширина 	= РазмерМассив[0];
		Высота	= РазмерМассив[1];
		
		ИмяСкрипта				= ПолучитьИмяВременногоФайла(".ps1");
		ТекстСкрипта			= Новый ТекстовыйДокумент();
		ТекстСкрипта.УстановитьТекст(
		"magick convert -resize " + Ширина + "x -unsharp 0x0.55+0.55+0.008 -quality 90 "
		+ ПутьКОригиналу 
		+ " "
		+ Путь 
		+ Размер.Ключ 
		+ ".webp"
		
		+ Символы.ПС +
		
		"convert "
		+ Путь 
		+ Размер.Ключ
		+ ".webp"
		+ " -resize " + Размер.Значение + "! -gravity North -extent " + Размер.Значение + " "
		+ Путь 
		+ Размер.Ключ
		+ ".webp"
		);
		
		ТекстСкрипта.Записать(ИмяСкрипта, КодировкаТекста.UTF8);				
		КодВозврата = 0;
		ЗапуститьПриложение("powershell -file " + ИмяСкрипта + " -noexit", ,Истина, КодВозврата);
		
		УдалитьФайлы(ИмяСкрипта);
		
	КонецЦикла;
	
КонецПроцедуры

Из незнакомого здесь: –quality и –unsharp. –quality может резать качество, что уменьшает вес картинки. Как работает unsharp никто не знает, но он снижает блюр при изменении размеров.

3. Еще один способ рисовать текст

Чтение и запись данных в excel файл из power shell

Рисует текст с подкладкой. Для этого используется вообще другой механизм: не -annotate, а –draw

magick event.jpg -fill white -stroke white -undercolor black -font Sylfaen -pointsize 28 -gravity SouthWest -draw "text 130,65 'Пабло Пикассо, Симона де Бовуар, Жан-Поль Сартр,\n Альбер Камю и другие'" event.jpg

stroke определяет цвет контура символов, –fill – цвет заливки, –udercolor – цвет подложки. 130, 65 после текст – те же +130+65 у annotate

Важно: \n – перенос строки

"magick """
	+ КартинкаОбработанная
	+ """ -fill white -stroke white -undercolor black -font Tahoma -pointsize 18 -gravity SouthWest -draw ""text 130,30 '"
	+ Место
	+ ", "
	+ ДатаСобытия
	+ "'"" """
	+ КартинкаОбработанная
	+ """"

Вот и вся “картиночная магия”. Надеюсь, было полезно.

Оставьте комментарий