Как я могу использовать пакетный скрипт для удаления папки и всего ее содержимого на основе имени папки в формате ГГГГММДД?

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

Скрипт ниже:

@echo off
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%"

set "datestamp=%YYYY%%MM%%DD%"

robocopy "\\fsfiles\d$" "D:\Backups\Inc\%datestamp%" /S /W:0 /R:1 /MAXAGE:1 /A-:SH

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

Скрипт ниже:

@echo off
:: set folder path
set dump_path=D:\Backups\Inc

:: set min age of files and folders to delete
set max_days=31

:: remove files from %dump_path%
forfiles -p %dump_path% -m *.* -d -%max_days% -c "cmd  /c del /q @path"

:: remove sub directories from %dump_path%
forfiles -p %dump_path% -d -%max_days% -c "cmd /c IF @isdir == TRUE rd /S /Q @path 

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

Как я могу этого добиться?


person Dr.Prog    schedule 06.04.2018    source источник
comment
В PowerShell все намного проще. Я рекомендую переключиться.   -  person Bill_Stewart    schedule 06.04.2018


Ответы (4)


Для исходного сценария нет ничего плохого в использовании WMIC для получения даты. Однако вы уже используете RoboCopy, поэтому вы можете использовать его для получения требуемой даты:

@Echo Off
For /F "Tokens=1-3 Delims=/ " %%A In ('RoboCopy/NJH /L "\|" Null'
) Do Set "ds=%%A%%B%%C"&GoTo BackUp
Exit /B
:BackUp
RoboCopy "\\fsfiles\D$" "D:\Backups\Inc\%ds%" /S /W:0 /R:1 /MaxAge:1 /A-:SH

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

Вот пример скрипта .ps1, который удалит каталоги со строками имен старше 1 месяца, (скорее всего, намеренно):

$MonthAgo = (Get-Date).AddMonths(-1)
$Folders = (Get-ChildItem "D:\Backups\Inc" | Where-Object {$_.PSIsContainer -Eq $True -And $_.Name -Match '^\d{8}'})
ForEach ($f In $Folders) {
    $FolderDate = Get-Date -Year $f.Name.SubString(0,4) -Month $f.Name.SubString(4,2) -Day $f.Name.SubString(6,2)
    If ($FolderDate -LT $MonthAgo) {
        Remove-Item $f.FullName -WhatIf
    }
}

… и аналогичным образом удалить каталоги со строками имен старше 31 дня:

$DaysAgo = (Get-Date).AddDays(-31)
$Folders = (Get-ChildItem "D:\Backups\Inc" | Where-Object {$_.PSIsContainer -Eq $True -And $_.Name -Match '^\d{8}'})
ForEach ($f In $Folders) {
    $FolderDate = Get-Date -Year $f.Name.SubString(0,4) -Month $f.Name.SubString(4,2) -Day $f.Name.SubString(6,2)
    If ($FolderDate -LT $DaysAgo) {
        Remove-Item $f.FullName -WhatIf
    }
}

Приведенные выше сценарии PowerShell не предназначены для фактического удаления каталогов, они просто показывают, что будет удалено. Чтобы удалить их, удалите -WhatIf из строки 6.

person Compo    schedule 06.04.2018
comment
Спасибо за совет по powershell! Можно ли создать журнал папок, удаленных через powershell? - person Dr.Prog; 06.04.2018
comment
Remove-Item не генерирует никакого вывода, обычный метод заключается в использовании Test-Path и проверке его существования вскоре после этого. Альтернативой может быть вывод -WhatIf в файл журнала, а затем запуск Remove-Item без этой опции. Вы даже можете вывести имена в журнал перед их удалением. Я оставлю это вам, чтобы исследовать и принять решение самостоятельно, поскольку поздний запрос технически выходит за рамки вашего первоначального вопроса. - person Compo; 06.04.2018

for /f "skip=%max_days%" %%d in ('dir /b /ad /o-n "%dump_path%\20*" ') do ECHO rd /s /q "%dump_path%\%%d"

был бы мой выбор.

Выполните dir в /b (базовом) режиме, показав только /ad каталогов в /o-n обратном порядке имен. Использование маски 20* "показывает" только имена каталогов, которые начинаются с 20.

Первые max_days строк пропускаются, когда for /f обрабатывает dir результат, поэтому остается 31 поколение.

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

person Magoo    schedule 06.04.2018
comment
Это предполагает, что OP делает резервную копию каждый день, у некоторых людей выходные, поэтому заявленным требованиям она не соответствует! Я согласен с тем, что он не удаляет то, что не должен, но может оставить то, что должно было быть удалено. - person Compo; 06.04.2018
comment
@Compo: Верно, но если OP уедет в круиз, то буквально за 31 день можно удалить слишком много резервных копий. Все зависит от того, насколько буквально следует интерпретировать время. - person Magoo; 06.04.2018

ИМХО, самое простое решение - НЕ просить партию выполнять арифметические действия с датами (Aquila non captat muscas :-))

Вместо этого попробуйте этот простой сценарий.

@echo off 
Setlocal EnableDelayedExpansion
set dump_path=D:\Backups\Inc
FOR /F "Usebackq" %%a IN (`DIR /AD /B /O-N "!dump_path!" ^| MORE +31`) DO (
    echo %%a
)

Очевидно, я поставил «эхо» вместо команды удаления, чтобы вы могли оценить, как это работает. Затем вы можете поместить команду удаления в круглые скобки.

По существу, если вы уверены, что ваши имена каталогов имеют форму ГГГГММДД, они перечислены в обратном порядке, исключая первые 31.

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

Надеюсь это поможет

person ienaxxx    schedule 06.04.2018
comment
Это предполагает, что ОП делает резервную копию каждый день, у кого-то выходные, поэтому она не соответствует заявленным требованиям! Я согласен с тем, что он не удаляет то, что не должен, но может оставить то, что должно было быть удалено. - person Compo; 06.04.2018
comment
Ты абсолютно прав. Хотя, если ОП регулярно выполняет резервное копирование (скажем, два раза в неделю), он может настроить расписание пакета удаления и +31 после команды MORE, чтобы действительно получить ожидаемый результат. - person ienaxxx; 06.04.2018

Поскольку ваш формат даты сортируется и сопоставим, я бы использовал:

@echo off
:: set folder path
set dump_path=D:\Backups\Inc
PushD "%dump_path%"

:: set min age of files and folders to delete
set max_days=31

:: Use PowerShell to eval max_days
for /f %%A in (
  'powershell -NoP -Noni -C "(Get-Date).AddDays(-%max_days%).ToString(\"yyyyMMdd\")"'
) Do set PurgeDate=%%A

For /F "tokens=*" %%A in ('Dir /B /ON "20*" '
) Do If "%%A" Gtr "20000101" if "%%A" Lss "%PurgeDate%" Echo RD /S /Q "%%A"

PopD
person Community    schedule 06.04.2018