Как написать свой первый скрипт PowerShell: Автоматизация очистки файлов

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

Обработка ошибок гарантирует, что вы создаете «сети» или место по умолчанию, куда ваш код может перейти, когда что-то неожиданное происходит.

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

Создание начального скрипта для очистки файлов

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

Задача звучит достаточно просто, но это раздел обработки ошибок, так что вы знаете, что что-то пойдет не так!

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

  1. Сначала откройте новую вкладку VS Code.

    Поскольку мы просто пробуем несколько вещей сейчас, мы пока не будем сохранять скрипт. Временно сообщите VS Code, что вы собираетесь написать что-то на PowerShell.

    Нажмите Ctrl-Shift-P, введите ‘lang’, выберите Выбрать режим языка, введите ‘power’ и выберите PowerShell. Теперь VS Code знает, что вы будете писать на PowerShell.

  2. Далее разбейте проблему на задачи, решая сначала самую очевидную.

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

    Get-ChildItem -Path C:\OldForgottenFolder
    
  3. Get-ChildItem также возвращает директории, которые нам не нужны, поэтому давайте ограничим это только файлами.

    Get-ChildItem -Path C:\OldForgottenFolder -File
    
  4. Если в этих подкаталогах есть файлы, нам нужно получить их тоже с помощью Recurse.

    Get-ChildItem -Path C:\OldForgottenFolder -File -Recurse
    
  5. Теперь, когда у нас есть команда и параметры, она возвращает ВСЕ файлы. Нам нужно найти только те, которые старше определенного количества дней.

    Поскольку Get-ChildItem возвращает каждый файл с свойством объекта LastWriteTime, нам нужно отфильтровать по этому свойству. Мы будем использовать фильтр Where, чтобы найти файлы с LastWriteTime, меньшим чем заданная дата.

    (Get-ChildItem -Path C:\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le ?????}
    
  6. Дата должна быть динамичной, потому что “старый” сегодня будет отличаться от “старого” завтра.

    Закомментируйте предыдущую строку, потому что она нам понадобится в какой-то момент, а затем разберитесь с ситуацией с датой.

    ## (Get-ChildItem -Path C:\\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le ?????}
    $Now = Get-Date
    $Now
    
  7. Теперь, когда у нас есть сегодняшняя дата, давайте найдем определенное количество дней до сегодняшнего дня, чтобы определить дату. Я временно поставлю 30 здесь, так как знаю, что некоторые файлы старше пяти дней, чтобы провести элементарный тест.

    ## (Get-ChildItem -Path C:\\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le ?????}
    $Now = Get-Date
    $LastWrite = $Now.AddDays(-30)
    $LastWrite
    
  8. Готово! Давайте соберем это вместе на данный момент.

    $Now = Get-Date
    $LastWrite = $Now.AddDays(-30)
    (Get-ChildItem -Path C:\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le $LastWrite}
    

    Теперь у нас есть небольшой скрипт, который находит все файлы в директории, которые старше определенного количества дней.

  9. Далее, мы должны добавить возможность удалять эти старые файлы. Это тривиально с использованием команды Remove-Item и конвейера.

    $Now = Get-Date
    $LastWrite = $Now.AddDays(-30)
    (Get-ChildItem -Path C:\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le $LastWrite} | Remove-Item
    
  10. Готово! Но подождите, у меня нет никакого представления о том, какие файлы были удалены. Также были некоторые ошибки, которые мы рассмотрим через несколько минут. Давайте добавим немного базовой функциональности.

    $VerbosePreference = 'Continue'
    
    $Now = Get-Date
    $LastWrite = $Now.AddDays(-30)
    $oldFiles = (Get-ChildItem -Path C:\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le $LastWrite}
    foreach ($file in $oldFiles) {
        Remove-Item -Path $file.FullName
        Write-Verbose -Message "Успешно удален [$($file.FullName)]."
    }
    
  11. Вам нужно будет включить цикл, подобный этому, чтобы выполнить какой-то код для каждого файла. Здесь мы не используем конвейер и вместо этого помещаем все найденные файлы в переменную oldFiles, массив объектов файлов. Затем мы выполняем Remove-Item для каждого из них, как раньше, но на этот раз включая подробное сообщение, сообщающее нам, какой файл удаляется.

  12. Теперь давайте запустим этот код и посмотрим, что произойдет.

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

Максимизация гибкости и повторного использования с помощью параметров

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

  1. Прежде чем мы продолжим, давайте сохраним нашу работу. Назовите его Remove-FileOlderThan.ps1.

    Обратите внимание на формат глагол/существительное с дефисом. Если возможно, старайтесь всегда создавать имена сценариев таким же образом, как и команды PowerShell для согласованности и читаемости.

  2. Во-первых, скрипты предназначены для повторного использования. Скорее всего, вы захотите использовать этот скрипт в разных каталогах и для разных сроков. Нам нужно будет ввести несколько параметров. Для этого мы определим, что будет изменяться. Каталог и количество дней. Понял.

    param (
        [Parameter(Mandatory)]
        [string]$FolderPath,
    [Parameter(Mandatory)]
    [int]$DaysOld
    

    )

    $Now = Get-Date
    $LastWrite = $Now.AddDays(-30)
    $oldFiles = (Get-ChildItem -Path C:\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le $LastWrite}
    foreach ($file in $oldFiles) {
    Remove-Item -Path $file.FullName
    Write-Verbose -Message "Успешно удалён [$($file.FullName)]."
    }

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

  3. Замените статические элементы, которые у нас были в коде ранее, значениями параметров.

    param (
        [Parameter(Mandatory)]
        [string]$FolderPath,
    [Parameter(Mandatory)]
    [int]$DaysOld
    

    )

    $Now = Get-Date
    $LastWrite = $Now.AddDays(-$DaysOld)
    $oldFiles = (Get-ChildItem -Path $FolderPath -File -Recurse).Where{$_.LastWriteTime -le $LastWrite}
    foreach ($file in $oldFiles) {
    Remove-Item -Path $file.FullName
    Write-Verbose -Message "Успешно удален [$($file.FullName)]."
    }

  4. Теперь давайте запустим скрипт и посмотрим, что произойдет.

    C:\Scripts\Remove-FileOlderThan.ps1 -FolderPath C:\OldForgottenFolder -DaysOld 30 -Verbose
    

    Вы можете увидеть, как мы должны указать путь к папке и количество дней в качестве параметров. Используйте параметр Verbose, чтобы увидеть строку Write-Verbose.

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

    Посмотрев на вывод, мы увидели некоторый красный текст. Либо у вас нет прав, либо файл доступен только для чтения. Но над какими файлами он не сработал? И как убедиться, что эти файлы также удалены?

    Заключение

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

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

    Следите за следующей демонстрацией! PowerShell 101: Завершающие и незавершающие ошибки, а также Try/Catch.

Source:
https://adamtheautomator.com/powershell-file-cleanup-script/