none
PowerShell Исключение нескольких папок с файлами из операции удаления файлов старше N дней RRS feed

  • Вопрос

  • Всем здравствуйте!

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

    $TargetDelNt = "D:\1"  #путь до папки шары
    $Del = "-3" #Количество хранимых дней
     
    $CurrentDay = Get-Date
     
    $ChDaysDel = $CurrentDay.AddDays($Del)
     
    #Удаление файлов, дата создания которых больше 3 дней
    GCI -Path $TargetDelNt -Recurse | Where-Object {$_.CreationTime -LT $ChDaysDel} | RI -Recurse -Force 
     
    #Удаление пустых папок
    GCI -Path $TargetDelNt -Recurse | Where-Object {
    $_.PSIsContainer -and 
    @(Get-ChildItem -Path $_.Fullname -Recurse  | Where { -not $_.PSIsContainer }).Count -eq 0 } | RI -Recurse 

    Этот скрипт работает все отлично.
    Но, появилась задача исключить несколько папок, так что бы скрипт не удалял конкретные папки и все что в них находиться.
    Попробовал сделать следующим образом:

    $TargetDelNt = "D:\1"  #путь до папки шары
    $Del = "-3" #Количество хранимых дней
     
    $CurrentDay = Get-Date
     
    $ChDaysDel = $CurrentDay.AddDays($Del)
     
    $Path1 = "D:\1\Не удалять" #Папка которую нужно исключить
    $Files1 = Get-ChildItem -Path $Path1 -Recurse #Собираю в переменную все что находиться в папке
     
    #Удаление файлов, дата создания которых больше 3 дней
    # Значением Exclude предотвращаю удаление нажных файлов 
    GCI -Path $TargetDelNt -Recurse -Exclude $Files1 | Where-Object {$_.CreationTime -LT $ChDaysDel} | RI -Recurse -Force 
     
    #Удаление пустых папок
    GCI -Path $TargetDelNt -Recurse | Where-Object {
    $_.PSIsContainer -and 
    @(Get-ChildItem -Path $_.Fullname -Recurse  | Where { -not $_.PSIsContainer }).Count -eq 0 } | RI -Recurse 

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

    18 апреля 2016 г. 6:32

Ответы

  • $folders = "C:\Folder1\T1","C:\Folder2\T2"
    GCI -Path $TargetDelNt -Recurse | Where {
    	$folder = $_.FullName
    	!($folders | Where {$folder.Contains($_)})
    }  | Where-Object {$_.CreationTime -LT $ChDaysDel} | RI -Recurse -Force



    • Предложено в качестве ответа KazunEditor 18 апреля 2016 г. 6:50
    • Отменено предложение в качестве ответа KazunEditor 18 апреля 2016 г. 6:50
    • Изменено KazunEditor 18 апреля 2016 г. 6:51
    • Помечено в качестве ответа KazunEditor 18 апреля 2016 г. 8:56
    18 апреля 2016 г. 6:43
    Отвечающий
  • 1 Попробуйте в Exclude запихнуть не файлы, а ваш путь только в конце добавьте слеш

    $Path1 = "D:\1\Не удалять\" #Папка которую нужно исключить
     
    #Удаление файлов, дата создания которых больше 3 дней
    # Значением Exclude предотвращаю удаление нажных файлов 
    GCI -Path $TargetDelNt -Recurse -Exclude $Path1 | Where-Object {$_.CreationTime -LT $ChDaysDel} | RI -Recurse -Force 
     

    2 можно любое количество фильтров впихнуть в Where

    $Path1 = "D:\1\Не удалять" #Папка которую нужно исключить
     
    #Удаление файлов, дата создания которых больше 3 дней
    # Значением Exclude предотвращаю удаление нажных файлов 
    GCI -Path $TargetDelNt -Recurse | Where-Object {($_.CreationTime -LT $ChDaysDel) -and ($_.Directory -ne $Path1)} | RI -Recurse -Force 
     


    The opinion expressed by me is not an official position of Microsoft

    • Помечено в качестве ответа KazunEditor 18 апреля 2016 г. 8:56
    18 апреля 2016 г. 6:47
    Модератор

Все ответы

  • $folders = "C:\Folder1\T1","C:\Folder2\T2"
    GCI -Path $TargetDelNt -Recurse | Where {
    	$folder = $_.FullName
    	!($folders | Where {$folder.Contains($_)})
    }  | Where-Object {$_.CreationTime -LT $ChDaysDel} | RI -Recurse -Force



    • Предложено в качестве ответа KazunEditor 18 апреля 2016 г. 6:50
    • Отменено предложение в качестве ответа KazunEditor 18 апреля 2016 г. 6:50
    • Изменено KazunEditor 18 апреля 2016 г. 6:51
    • Помечено в качестве ответа KazunEditor 18 апреля 2016 г. 8:56
    18 апреля 2016 г. 6:43
    Отвечающий
  • 1 Попробуйте в Exclude запихнуть не файлы, а ваш путь только в конце добавьте слеш

    $Path1 = "D:\1\Не удалять\" #Папка которую нужно исключить
     
    #Удаление файлов, дата создания которых больше 3 дней
    # Значением Exclude предотвращаю удаление нажных файлов 
    GCI -Path $TargetDelNt -Recurse -Exclude $Path1 | Where-Object {$_.CreationTime -LT $ChDaysDel} | RI -Recurse -Force 
     

    2 можно любое количество фильтров впихнуть в Where

    $Path1 = "D:\1\Не удалять" #Папка которую нужно исключить
     
    #Удаление файлов, дата создания которых больше 3 дней
    # Значением Exclude предотвращаю удаление нажных файлов 
    GCI -Path $TargetDelNt -Recurse | Where-Object {($_.CreationTime -LT $ChDaysDel) -and ($_.Directory -ne $Path1)} | RI -Recurse -Force 
     


    The opinion expressed by me is not an official position of Microsoft

    • Помечено в качестве ответа KazunEditor 18 апреля 2016 г. 8:56
    18 апреля 2016 г. 6:47
    Модератор
  • Не работает ни в одном случае. Файлы старше 3 дней удаляются(
    18 апреля 2016 г. 7:12
  • $folders = "C:\Folder1\T1","C:\Folder2\T2"
    GCI -Path $TargetDelNt -Recurse | Where {
    	$folder = $_.FullName
    	!($folders | Where {$folder.Contains($_)})
    }  | Where-Object {$_.CreationTime -LT $ChDaysDel} | RI -Recurse -Force



    Не работает(

    18 апреля 2016 г. 7:12
  • Показывайте вывод, где попадают папки, которые должны быть исключены:

    $folders = "C:\Folder1\T1","C:\Folder2\T2"
    GCI -Path $TargetDelNt -Recurse | Where {
    	$folder = $_.FullName
    	!($folders | Where {$folder.Contains($_)})
    } | Ft FullName -Auto



    • Изменено KazunEditor 18 апреля 2016 г. 7:18
    18 апреля 2016 г. 7:16
    Отвечающий
  • Показывайте вывод, где попадают папки, которые должны быть исключены:

    $folders = "C:\Folder1\T1","C:\Folder2\T2"
    GCI -Path $TargetDelNt -Recurse | Where {
    	$folder = $_.FullName
    	!($folders | Where {$folder.Contains($_)})
    } | Ft FullName -Auto



    Вывод такой

    PS D:\1> $folders = "D:\1\Не удалять"
    GCI -Path $TargetDelNt -Recurse | Where {
    	$folder = $_.FullName
    	!($folders | Where {$folder.Contains($_)})
    } | Ft FullName -Auto
    
    FullName      
    --------      
    D:\1\Удалить1 
    D:\1\Удалить2 
    D:\1\clear.ps1

    НО! Если вставить вместо вывода RI -Recurse -Force, то файлы удаляет и из папки "Не удалять"((

    18 апреля 2016 г. 7:34
  • Теперь вывод с ключом -WhatIf, который только уведомляет, а не удаляет.

    $folders = "D:\1\Не удалять"
    GCI -Path $TargetDelNt -Recurse | Where {
    	$folder = $_.FullName
    	!($folders | Where {$folder.Contains($_)})
    } | Where-Object {$_.CreationTime -LT $ChDaysDel} | RI -Recurse -Force -WhatIf

    18 апреля 2016 г. 7:39
    Отвечающий
  • Теперь вывод с ключом -WhatIf, который только уведомляет, а не удаляет.

    $folders = "D:\1\Не удалять"
    GCI -Path $TargetDelNt -Recurse | Where {
    	$folder = $_.FullName
    	!($folders | Where {$folder.Contains($_)})
    } | Where-Object {$_.CreationTime -LT $ChDaysDel} | RI -Recurse -Force -WhatIf

    PS D:\1> $TargetDelNt = "D:\1" 
    $Del = "-3"
    $CurrentDay = Get-Date
    $folder = "D:\1\Не удалять"
    $ChDaysDel = $CurrentDay.AddDays($Del)
    GCI -Path $TargetDelNt -Recurse | Where {
    	$folder = $_.FullName
    	!($folders | Where {$folder.Contains($_)})
    }  | Where-Object {$_.CreationTime -LT $ChDaysDel} | RI -Recurse -Force -WhatIf
    WhatIf: Выполнение операции "Удаление файла" над целевым объектом "D:\1\Не удалять\Документ3.docx".
    У файла "Документ3.docx" Дата создания больше 3 дней
    18 апреля 2016 г. 8:09
  • $folder = "D:\1\Не удалять" должно быть всегда $folders = "D:\1\Не удалять"
    • Изменено KazunEditor 18 апреля 2016 г. 8:11
    18 апреля 2016 г. 8:11
    Отвечающий
  • Извиняюсь( проглядел.
    18 апреля 2016 г. 8:15
  • Интересно получается, вот код:

    $TargetDelNt = "D:\1"
    $Del = "-3"
    $CurrentDay = Get-Date
    $folders = "D:\1\Не удалять"
    $ChDaysDel = $CurrentDay.AddDays($Del)
    
    GCI -Path $TargetDelNt -Recurse | Where {
    	$folder = $_.FullName
    	!($folders | Where {$folder.Contains($_)})
    } | Where-Object {$_.CreationTime -LT $ChDaysDel} | RI -Recurse -Force -WhatIf

    Если выполнять все писать руками в PowerShell то выводит:

    $TargetDelNt = "D:\1" 
    $Del = "-3"
    $CurrentDay = Get-Date
    $folders = "D:\1\Не удалять"
    $ChDaysDel = $CurrentDay.AddDays($Del)
    GCI -Path $TargetDelNt -Recurse | Where {
    	$folder = $_.FullName
    	!($folders | Where {$folder.Contains($_)})
    } | Where-Object {$_.CreationTime -LT $ChDaysDel} | RI -Recurse -Force -WhatIf
    WhatIf: Выполнение операции "Удаление файла" над целевым объектом "D:\1\Удалить1\Документ2.docx".

    То есть все правильно, папку "Не удалять" он не трогает, а файл "Документ2.docx" с датой создания больше 3 дней он удаляет.

    А если этот скрипт сохранить в файл "clear.ps1" и запустить из PowerShell то совершенно другая ситуация

    PS D:\1> .\clear.ps1
    WhatIf: Выполнение операции "Удаление файла" над целевым объектом "D:\1\Не удалять\Документ3.docx".
    WhatIf: Выполнение операции "Удаление файла" над целевым объектом "D:\1\Удалить1\Документ2.docx".

    Скрипт пытается удалить из всех папок.

    теперь я вообще ничего не понимаю O_o

    18 апреля 2016 г. 8:58
  • Скриншот приведите:

    Get-Content .\clear.ps1

    18 апреля 2016 г. 9:01
    Отвечающий
  • Спасибо за наводку)

    Дело было в кодировке. Notepad++ стояла кодировка UTF - 8 (Без BOM)

    И PowerShell были крокозябры

    Поменял кодировку на UTF-8 и все нормально заработало)

    Спасибо большое

    18 апреля 2016 г. 9:21