Нравится

Уроки Powershell – работа с файлами и папками

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

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

Казалось бы, все банально, есть командлеты Item которые позволяют создавать (New-Item), удалять (Remove-Item), копировать (Copy-Item) и переименовывать (Rename-Item) и выжать из этого ничего нельзя, но я попробую.

Теория

По сути своей мало что изменилось, более правильно сказать «видоизменилось», и получило новые возможности которые несомненно пригодятся для работы. Если внимательно присмотреться то видно что старые команды поддерживаются через псевдонимы, вернее псевдонимы облегчают переход и поэтому освоение новых команд облегчено и снабжено богатым справочным материалом.

Давайте вернемся к вопросу преемственности поколений… Тьфу. Перехода на новые синтаксис :)

Первым на что следует посмотреть это аналог хорошо знакомой команды dir, это командлет Get-Children.

Примечание: Действие командлета Get-Children его распространяется не только на файловую систему. Но об этом позже.

В консоли PowerShell введите команду dir, нажмите Enter, затем Get-ChildItem D:\Script и снова Enter, посмотрите на результаты. Они одинаковы. Поптому что dir является алиасом к Get-Children.

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

Как дополнительный пример можно привести аналог для dir /S которая рекурсивно выводит список файлов будет команда.

Get-ChildItem -Force D:\Script -Recurse

На замену dir *.exe пришла возможность фильтрации элементов при помощи параметров Path, Filter, Include и Exclude.

Примечание: В своей практике я видел множество вариантов использования но чаще всего фильтрация осуществлялась лишь по имени.

Добавилась сложная фильтрация элементов при помощи командлета Where-Object (сокращенное написание Where).

Простой пример фильтрации по расширению.

Get-ChildItem -Path C:\Windows | Where {$_.extension -eq ".dll"}

Дополнение: PowerShell использует в качестве подстановочных знаков не только ? и * как это было в cmd.exe, но и группы символов в квадратных скобках.

Поэтому если вы попробуете найти файл Script[01].ps1 командой

Get-ChildItem ‘.\Script[01].ps1′

То получите ошибку.
В этом случае необходимо использовать параметр -LitealPath

Get-ChildItem  -LiteralPath ‘.\Script[01].ps1′

Более сложный вариант выполнит поиск архивов в папке D:\Backup, созданных после 1 мая 2011 года, размер которых  находится в диапазоне 10-100 Мб.

Get-ChildItem -Path D:\Backup -Recurse -Include *.zip | Where-Object -FilterScript {($_.LastWriteTime -gt "2011-05-01") -and ($_.Length -ge 10mb) -and ($_.Length -le 100mb)}

Опции Include и Exclude работают соответственно своим названиям т.е. первая включает а вторая исключает заданный фильтр из поиска.

$exclude = @(‘*.dll’,‘*.exe’)
$include = @(‘*.txt’,‘*.ps1′)
$result1 = Get-ChildItem "C:\Script" -Recurse -Exclude $exclude
$result2 = Get-ChildItem "D:\Script" -Recurse -Include $include

Перейдем к вопросу копирования файлов.

Аналогом команды copy стал командлет Copy-Item.

Copy-Item -Path D:\Script\script-01.ps1 -Destination E:\Backup\27-09-2011\script-01.ps1

В случае если целевой файл уже существует, при попытке его скопировать вы встретите ругань красного цвета :) и процесс копирования закончится. Для перезаписи целевого файла используется параметр Force:

Copy-Item -Path D:\Script\script-01.ps1 -Destination E:\Backup\27-09-2011\script-01.ps1 -Force

Примечание: Ключ Force работает даже когда целевой файл помечен как файл только для чтения.

Копирование дерева папок выполняется той же командой, но с указанием ключа Recurse.

Copy-Item -Path D:\Script -Recurse E:\Backup\27-09-2011

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

Copy-Item -Filter *.txt  -Path D:\Script -Recurse E:\Backup\27-09-2011

Создание файлов и папок средствами PowerShell производится с помощью командлета New-Item.

Для создания папки придется указать тип элемента «Directory», а для создания файла «File»

New-Item -Path ‘D:\Script\New Folder’ -ItemType "directory"
New-Item -Path ‘D:\Script\New Folder\script-02.ps1′ -ItemType "file"

Примечание: Старая команда mkdir, позволяющая создавать папки получила новую жизнь в виде алиаса md.

Переименование элементов производится с помощью команды Rename-Item.

Rename-Item .\File-01.ps1 .\File-01.ps1.bak

Удаление производится с помощью Remove-Item.

Удалить вложенные в папку элементы можно при помощи командлета Remove-Item, однако он потребует подтверждения удаления, если элемент сам что-нибудь содержит. К примеру, в случае если мы пытаемся удалить папку  d:\Backup\20-09-2011, содержащую другие элементы, powershell предложит подтвердить свои действия. Для того что бы этого не происходило (подумайте о том дествительно ли вам нужно удалять :) )

Remove-Item d:\Backup\20-09-2011 -Recurse

Практика

Практическое применение всего вышесказанного может быть разнообразно.

Например, может быть задача поиска в лог файлах определенного выражения по маске ip-адреса «192.168.100.253″ с последующим копированием найденного в папку D:\TEMP, вариантов множество, вот метод поиска:

$current = Get-Date
$Days = "-30"
$start = $current.AddDays($days)
Get-ChildItem D:\Logs -Filter *.log -Recurse | Where-Object {($_.LastWriteTime.Date -ge $Start.Date) -and ($_.LastWriteTime.Date -le $End.Date)} | Select-String "192.168.100.253" | Copy-Item -Destination D:\TEMP

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

$Path = "C:\temp"
$Days = "-30"
$CurrentDate = Get-Date
$OldDate = $CurrentDate.AddDays($Days)
Get-ChildItem $Path | Where-Object { $_.LastWriteTime -lt $OldDate } | Remove-Item

Или если вам требуется удалять все что есть в папке и в подпапках т.е. удаление еще и самих папок.

$Path = "C:\temp"
$Days = "-30"
$CurrentDate = Get-Date
$OldDate = $CurrentDate.AddDays($Days)
Get-ChildItem $Path -Recuse | Where-Object { $_.LastWriteTime -lt $OldDate } | Remove-Item

PS. Альтернативный метод решения задачи удаления временных файлов скриптом по расписанию вы можете найти в блоге Вадима Стеркина. Рекомендую.

Приглашаю присоединиться ко мне в следующих сервисах:
facebook Google Plus вКонтакте Twitter
Если Вам понравилась статья, то вы можете подписаться на RSS. А также бесплатно подписаться по E-mail и получать актуальную информацию в числе первых.
Получать обновления на email

Вы можете оставить комментарий.

21 Комментариев »

 
  • 1# Vadim Sterkin (22 комм.):

    Сергей, добавь, плиз, якорь в абзац «Можно придумать сценарий когда на файловой помойке». Я поставлю ссылку в Удаление временных файлов скриптом по расписанию

      Цитировать

  • 3# Vadim Sterkin (22 комм.):

    Не вижу якоря :) Я предлагал вставить в абзац

    (надеюсь, тег code не позволит съесть ссылку в комменте)

    Я бы тогда сослался прямо на абзац.

      Цитировать

  • 8# Kazun (76 комм.):

    «Если внимательно присмотреться то видно что старые команды поддерживаются через псевдонимы, а освоение новых облегчего богатым справочным материалом.» – старые команды не поддерживаются через псевдонимы,псевдонимы лишь облегчают переход с других платформ и сред.

    «Более сложный вариант выполнит поиск архивов в папке D:\Backup, созданных после 1 мая 2011 года, размер которых не превышает 100 мб.» – и больше 10 мб ( в пределах 10-100 мб).

    «В случае если целевой файл уже существует, при попытке его скопировать вы встретите ругань красного цвета и процесс копирования закончится. » – если не хватает прав на запись,стоят аттрибуты S,R,вот тогда мы получим ошибку.

    Для создание папок,если Вы начали в начале статьи про «старые командлы»,можно рассказать про md,который является альясом mkdir(в свою очередь является proxy function).

    «Можно придумать сценарий когда на файловой помойке требуется из определенной папки удалять все файлы старше 30 дней.» – но и за одно и папки удалим.

    «Или если вам требуется удалять все что есть в папке и в подпапках» – вместе с подпапками

    Так же нет упоминание про параметр -LiteralPath,он очень важен,когда есть подстановочные знаки или escape сиволы.

      Цитировать

    • 9# Сергей Мариничев (565 комм.):

      1. Согласен. Сказано для простоты восприятия. Человека порою пугает когда его знакомая команда copy вдруг отсутствует.
      2. Спасибо. Исправил.
      3. по умолчанию я считаю что права есть. Пытаться перезаписать файлы на которые нет прав не совсем правильно.
      4. Подправил.
      5. 6. :)
      7. Ценное дополнение. Сейчас допишу.

        Цитировать

  • 10# Kazun (76 комм.):

    Get-ChildItem ‘.\Script[01].ps1′ -LiteralPath – поправьте ошибку

    3) По третьему пункту,я имел ввиду,то что если нет атрибутов RS ,то ошибки не получим, в случае – существования конечного файла.

      Цитировать

    • 11# Сергей Мариничев (565 комм.):

      Подправил это и еще пару опечаток.
      Говорил я себе – публиковать надо в начале дня и только на свежую голову т.к. мелких ошибок и опечаток можно будет и не заметить.

        Цитировать

  • 12# nanolarge (1 комм.):

    Любопытная статья, да и сам сайт я смотрю очень даже не плох. Попал сюда по поиску из Google, занес в букмарки :)

      Цитировать

  • 13# maks (1 комм.):

    Get-ChildItem $Path -Recuse | Where-Object { $_.LastWriteTime -lt $OldDate } | Remove-Item – поправьте -Recurse
    «Или если вам требуется удалять все что есть в папке и в подпапках т.е. удаление еще и самих папок.» – точно сами подпапки удаляются ? Я попробовал с ключем -WhatIf ? показывает что будут удалены только файлы (в папке и подпапке) но не сама подпапка..

      Цитировать

    • 14# Сергей Мариничев (565 комм.):

      Спасибо за комментарий.
      Зачем удалять папки?
      Их нужно удалять только в случае если они пустые. Хотя если есть такая необходимость ваш метод предпочтительнее.

        Цитировать

  • 15# Сержо (4 комм.):

    Всем доброго времени суток!!! Нужна помощь!
    Мне нужно чтоб из папки, удалялись все файлы старше 3х дней, кроме последних двух, как это реализовать?
    Щас проблема в том что если файлы не добавились в папку, а оставшиеся стали больше трех дней, то скрипт все удаляет!

      Цитировать

  • 20# Сержо (4 комм.):

    Система значит такая удаляються файлы старше 3хдней, есть 5 файлов, каждый создан в разное время!
    файл1 создан 1.01.2012;
    файл2 создан 5.01.2012;
    файл3 создан 7.01.2012;
    файл4 создан 11.01.2012;
    файл5 создан 13.01.2012;
    на момент удаления число 20.01.2012, скрипт удаляет все эти файлы так как они устаревшие, а мне нужно чтоб файл4 и файл5 не удалился! А когда появяться новые файлы!
    файл4 создан 11.01.2012;
    файл5 создан 13.01.2012;
    файл6 создан 7.02.2012;
    файл7 создан 11.02.2012;
    файл8 создан 13.02.2012;
    скрипт на 20.02 2012 должен удалить все кроме файл7, файл8!

      Цитировать

 

Добавить комментарий

XHTML: Вы можете использовать тэги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>