понедельник, 4 января 2010 г.

Windows PowerShell

Очень удобное средство в Windows для написания различных скриптов, автоматизирующих работу. Более мощное средство, чем стандартные cmd-скрипты. Файлы powershell-скриптов имеют расширение ".ps1". Вот пример простенького скрипта, в котором мы архивируем файлы с помощью 7-zip и копируем их в архивную папку:
# archive files using 7-zip
$application = "C:\Program Files\7-zip\7z.exe"
$arguments = "a -tzip C:\xls.zip -r  F:\results\xls\*.*"
$process = [Diagnostics.Process]::Start($application, $arguments)
do { } while (!$process.HasExited)
# create new folder and copy file
$curdate = get-date -format "yyyyMMdd"
$src = "C:\xls.zip"
$dest = "D:\archives\$curdate"
New-Item $dest -type directory -force
Copy-Item $src "$dest\xls.zip"
Стоит особо пояснить строку do {  } while (!$process.HasExited). Здесь мы проверяем в цикле состояние запущенного процесса и скрипт не продолжит выполнятся, пока процесс создания файла архива полностью не завершится. Вместо этой конструкции можно использовать
$process.WaitForExit()
или вообще все в одну строчку лаконично уместить:
[Diagnostics.Process]::Start($application, $arguments).WaitForExit()

Инода возникает необходимость узнать дату, которая, предшествующую текущему времени и использовать ее, допустим, в названии архивной папки. Это можно сделать, например, таким образом:
# get date before 30 days ago
$date = (Get-Date).AddDays(-30)
$datestr= "{0:yyyyMM}" -f $date
$path = "D:\archives\$datestr"
В результате переменная $path будет чем-то вроде  "D:\archives\200912".
Удобно работать с файлами. Следующий скрипт, например, выводит список файлов и их размер:
foreach ($file in Get-ChildItem "F:\old_bases\DBF")
{
   $file.name + " " +$file.length
}
В нижеприведенном примере происходит копирование файлов из одних папок в другие при помощи цикла foreach:
foreach ($depNo in 40..75)
{
   if(($depNo -gt 66) -and ($depNo -lt 72)) { continue }
   $src = "F:\resultxls\dep" + $depNo + "\tables"
   $dst = "T:\backup\dep" + $depNo+ "\tables"
   Copy-Item "$src\*.xls" -destination "$dst"
  
   "files to dep$depNo are copied"
}
Что интересно, запуск скриптов можно осуществлять как набрав в консоли паэршелла полный путь скрипта типа "D:\scripts\ps1scripts\test.ps1", так и "D:\scripts/ps1scripts/test.ps1". Причем при указании пути во втором случае при указании диска используется обратный слеш, а при указании пути прямой. Также можно в консоли пауэршелла применить команду cd и сделать нужную папку со скрипатми текущей, и вызвать из ее корня необходимый скрипт, набрав "./script.ps1". То есть точка и прямой слеш подразумевают текущую директорию.

Кстати говоря, сначала файлы скриптов не исполнялись, т.к. их запуск был запрещен политикой по умолчанию. Чтобы разрешить запуск скриптов, установим в powershell соответствующую политику безопасности:
Set-ExecutionPolicy Unrestricted
 Взято отсюда:
- список команд с описанием
- включение политик
- простенький примерчик
- особое спасибо автору этого поста про запуск консольных программ в пауэршелле
- и этим людям за раскрытие темы контроля состояния запущенного процесса
- форматирование строк