【问题标题】:Batch file to delete files and folder批处理文件删除文件和文件夹
【发布时间】:2012-11-11 02:33:15
【问题描述】:

我正在寻找一种方法来删除包含在具有特定名称的文件夹中的文件,然后再删除该文件夹。

我知道有 forfiles 命令行可以用来删除文件,我只是不知道如何将文件夹名称放入路径中。该文件夹是根据创建日期命名的,我想删除 7 天前的文件夹。文件夹格式为 yyyymmdd。

基本上我需要

forfiles /P "C:\backups\[DATE 7 DAYS AGO IN yyyymmdd format]" /S /M *.BAK /C "cmd /c del @path"

然后我想删除文件夹之后就可以了

forfiles /P "C:\backups\[DATE 7 DAYS AGO IN yyyymmdd format]" /S /C "cmd /c IF @isDir == TRUE rd @path"

如何为这些填写 [DATE 7 DAYS AGO ...]。

【问题讨论】:

    标签: windows batch-file command-line


    【解决方案1】:

    第一个 - 为什么您尝试先删除文件,然后再删除 tolfer?如果您先删除该文件夹,您将在更短的时间内做同样的事情......

    2nd - 我认为您不能批量执行此操作,并非没有错误,您需要提取(知道)您需要使用的至少“X”年的日历日您的目的,而 Batch 没有任何方法可以提取该信息,也无法成为知道如何获取过去几年日历日期的数学天才。

    因此您需要一种可以访问 Microsoft.Time 和数据库并进行比较的现实脚本语言。 (Ruby、Python、Perl,所有你想要的更少 Batch)

    顺便说一句,存在一些由 RobVanDeerWoud 编写的超高级算法 batfile 代码,用于“玩”事物,例如使用此脚本您可以将“X”天添加到日期,看看是否可以修改以扣除天:

    (代码作者:ROBVANDERWOUD)

    DATEADD.BAT:
    
    
    
    @ECHO OFF
    ECHO.
    
    :: Check the Windows version
    IF NOT "%OS%"=="Windows_NT" GOTO Syntax
    SETLOCAL
    
    :: Initialize variable
    SET Error=0
    
    :: Check the command line arguments
    IF     "%~1"=="" GOTO Syntax
    IF NOT "%~3"=="" GOTO Syntax
    IF "%~2"=="" (
        FOR %%A IN (%Date%) DO SET cDate=%%A
        SET cDays=%~1
    ) ELSE (
        SET cDate=%~1
        SET cDays=%~2
    )
    
    :: Read the Date format from the registry
    CALL :ReadDateFormat
    
    :: Check if a valid date was specified
    (ECHO.%cDate%) | FINDSTR /R /B /C:"[0-9]*\%sDate%[0-9]*\%sDate%[0-9]*" >NUL
    IF ERRORLEVEL 1 (
        ECHO Error: %cDate% is not a valid date
        ECHO.
        GOTO Syntax
    )
    
    :: Check if the second argument is a valid number
    (ECHO.%cDays%) | FINDSTR /R /B /C:"-*[0-9]*" >NUL
    IF ERRORLEVEL 1 (
        ECHO Error: %cDays% is not an integer
        ECHO.
        GOTO Syntax
    )
    
    :: Parse the date specified
    CALL :ParseDate %cDate%
    
    :: Check for errors
    IF %Error% NEQ 0 GOTO Syntax
    
    :: Convert the parsed Gregorian date to Julian
    CALL :JDate %GYear% %GMonth% %GDay%
    
    :: Display original input
    ECHO Starting date   : %cDate%
    
    :: Add or subtract the specified number of days
    IF "%cDays:~0,1%"=="-" (
        SET /A NewJDate = %JDate% - %cDays:~1%
        ECHO Days subtracted : %cDays:~1%
    ) ELSE (
        SET /A NewJDate = %JDate% + %cDays%
        ECHO Days added      : %cDays%
    )
    
    :: Convert the new Julian date back to Gregorian again
    CALL :GDate %NewJDate%
    
    :: Reformat the date to local format
    CALL :ReformatDate %GDate%
    
    :: Display the result
    ECHO Resulting date  : %LDate%
    
    :: Return the result in a variable named after this batch file
    ENDLOCAL & SET %~n0=%LDate%
    GOTO:EOF
    
    
    ::===================================::
    ::                                   ::
    ::   -   S u b r o u t i n e s   -   ::
    ::                                   ::
    ::===================================::
    
    
    :GDate
    :: Convert Julian date back to "normal" Gregorian date
    :: Argument : Julian date
    :: Returns  : YYYY MM DD
    ::
    :: Algorithm based on Fliegel-Van Flandern
    :: algorithm from the Astronomical Almanac,
    :: provided by Doctor Fenton on the Math Forum
    :: (http://mathforum.org/library/drmath/view/51907.html),
    :: and converted to batch code by Ron Bakowski.
    ::
    SET /A P      = %1 + 68569
    SET /A Q      = 4 * %P% / 146097
    SET /A R      = %P% - ( 146097 * %Q% +3 ) / 4
    SET /A S      = 4000 * ( %R% + 1 ) / 1461001
    SET /A T      = %R% - 1461 * %S% / 4 + 31
    SET /A U      = 80 * %T% / 2447
    SET /A V      = %U% / 11
    SET /A GYear  = 100 * ( %Q% - 49 ) + %S% + %V%
    SET /A GMonth = %U% + 2 - 12 * %V%
    SET /A GDay   = %T% - 2447 * %U% / 80
    :: Clean up the mess
    FOR %%A IN (P Q R S T U V) DO SET %%A=
    :: Add leading zeroes
    IF 1%GMonth% LSS 20 SET GMonth=0%GMonth%
    IF 1%GDay%   LSS 20 SET GDay=0%GDay%
    :: Return value
    SET GDate=%GYear% %GMonth% %GDay%
    GOTO:EOF
    
    
    :JDate
    :: Convert date to Julian
    :: Arguments : YYYY MM DD
    :: Returns   : Julian date
    ::
    :: First strip leading zeroes
    SET MM=%2
    SET DD=%3
    IF %MM:~0,1% EQU 0 SET MM=%MM:~1%
    IF %DD:~0,1% EQU 0 SET DD=%DD:~1%
    ::
    :: Algorithm based on Fliegel-Van Flandern
    :: algorithm from the Astronomical Almanac,
    :: provided by Doctor Fenton on the Math Forum
    :: (http://mathforum.org/library/drmath/view/51907.html),
    :: and converted to batch code by Ron Bakowski.
    SET /A Month1 = ( %MM% - 14 ) / 12
    SET /A Year1  = %1 + 4800
    SET /A JDate  = 1461 * ( %Year1% + %Month1% ) / 4 + 367 * ( %MM% - 2 -12 * %Month1% ) / 12 - ( 3 * ( ( %Year1% + %Month1% + 100 ) / 100 ) ) / 4 + %DD% - 32075
    FOR %%A IN (Month1 Year1) DO SET %%A=
    GOTO:EOF 
    
    
    :ParseDate
    :: Parse (Gregorian) date depending on registry's date format settings
    :: Argument : Gregorian date in local date format,
    :: Requires : sDate (local date separator), iDate (local date format number)
    :: Returns  : GYear (4-digit year), GMonth (2-digit month), GDay (2-digit day)
    ::
    IF %iDate%==0 FOR /F "TOKENS=1-3 DELIMS=%sDate%" %%A IN ('ECHO.%1') DO (
        SET GYear=%%C
        SET GMonth=%%A
        SET GDay=%%B
    )
    IF %iDate%==1 FOR /F "TOKENS=1-3 DELIMS=%sDate%" %%A IN ('ECHO.%1') DO (
        SET GYear=%%C
        SET GMonth=%%B
        SET GDay=%%A
    )
    IF %iDate%==2 FOR /F "TOKENS=1-3 DELIMS=%sDate%" %%A IN ('ECHO.%1') DO (
        SET GYear=%%A
        SET GMonth=%%B
        SET GDay=%%C
    )
    IF %GDay%   GTR 31 SET Error=1
    IF %GMonth% GTR 12 SET Error=1
    GOTO:EOF
    
    
    :ReadDateFormat
    :: Read the Date format from the registry.
    :: Arguments : none
    :: Returns   : sDate (separator), iDate (date format number)
    ::
    :: First, export registry settings to a temporary file:
    START /W REGEDIT /E "%TEMP%.\_TEMP.REG" "HKEY_CURRENT_USER\Control Panel\International"
    :: Now, read the exported data:
    FOR /F "tokens=1* delims==" %%A IN ('TYPE "%TEMP%.\_TEMP.REG" ˆ| FIND /I "iDate"') DO SET iDate=%%B
    FOR /F "tokens=1* delims==" %%A IN ('TYPE "%TEMP%.\_TEMP.REG" ˆ| FIND /I "sDate"') DO SET sDate=%%B
    :: Remove the temporary file:
    DEL "%TEMP%.\_TEMP.REG"
    :: Remove quotes from the data read:
    :: SET iDate=%iDate:"=%
    FOR %%A IN (%iDate%) DO SET iDate=%%~A
    :: SET sDate=%sDate:"=%
    FOR %%A IN (%sDate%) DO SET sDate=%%~A
    GOTO:EOF
    
    
    :ReformatDate
    :: Reformat the date back to the local format
    :: Arguments : YYYY MM DD
    :: Returns   : LDate (Gregorian date in local format)
    ::
    IF %iDate%==0 SET LDate=%2%sDate%%3%sDate%%1
    IF %iDate%==1 SET LDate=%3%sDate%%2%sDate%%1
    IF %iDate%==2 SET LDate=%1%sDate%%2%sDate%%3
    GOTO:EOF
    
    
    :Syntax
    ECHO DateAdd.bat,  Version 1.10 for Windows NT 4 / 2000 / XP / Server 2003 / Vista
    ECHO Add (or subtract) the specified number of days to (or from) the specified date
    ECHO.
    ECHO Usage:  DATEADD  [ date ]  days
    ECHO.
    ECHO Where:  "date"   is a "normal" Gregorian date in the local computer's format
    ECHO                  (default value if no date is specified: today's date)
    ECHO         "days"   is the number of days to add or subtract
    ECHO.
    IF     "%OS%"=="Windows_NT" FOR %%A IN (%Date%) DO SET Today=%%A
    IF     "%OS%"=="Windows_NT" ECHO E.g.    DATEADD %Today%  1 will return tomorrow's date  (as will DATEADD  1)
    IF     "%OS%"=="Windows_NT" ECHO         DATEADD %Today% -1 will return yesterday's date (as will DATEADD -1)
    IF     "%OS%"=="Windows_NT" ENDLOCAL
    IF NOT "%OS%"=="Windows_NT" ECHO E.g.    DATEADD 01/25/2007  1 should return 01/26/2007
    IF NOT "%OS%"=="Windows_NT" ECHO         DATEADD 01/25/2007 -1 should return 01/24/2007
    ECHO.
    ECHO Julian date conversion based on Fliegel-Van Flandern algorithms from
    ECHO the Astronomical Almanac, provided by Doctor Fenton on the Math Forum
    ECHO (http://mathforum.org/library/drmath/view/51907.html), and converted
    ECHO to batch code by Ron Bakowski.
    ECHO.
    ECHO Written by Rob van der Woude
    ECHO http://www.robvanderwoude.com 
    

    【讨论】:

      【解决方案2】:

      尝试使用rmdir(在命令提示符下键入rmdir /? 寻求帮助)

      【讨论】:

        【解决方案3】:

        好吧,我听从了 Elektro Hacker 的建议,最终通过 powershell 完成了这项工作,如下所示:

        $currentDate = get-date
        $backupPath = "C:\backup\"
        $logFilePath = ("$backupPath" + "ScriptAndQuery\Logs\")
        
        $dailyLog = ("$logFilePath" + "daily_delete.txt")
        $weeklyLog = ("$logFilePath" + "weekly_delete.txt")
        $monthlyLog = ("$logFilePath" + "monthly_delete.txt")
        
        $dailyBackup = ("$backupPath" + "Daily\")
        $weeklyBackup = ("$backupPath" + "Weekly\")
        $monthlyBackup = ("$backupPath" + "Monthly\")
        
        $addDateToFile = "TRUE"
        
        get-childitem $dailyBackup |? { $_.psiscontainer -and $_.lastwritetime -le ($currentDate).adddays(-7) } |% { 
            try {
                if($addDateToFile -eq "TRUE") {
                    Add-Content "$dailyLog" "$currentDate`r`n"
                    $addDateToFile = "FALSE"
                }
        
                $fullPath = $_.FullName
                remove-item $fullPath -Recurse -force
        
                if (test-path $fullPath) {
                    Add-Content "$dailyLog" "FAILED TO DELETE $fullPath`n"
                } else {
                    Add-Content "$dailyLog" "SUCCESSFULLY DELETED $fullPath`n"
                }
            }
            catch {
                Add-Content "$dailyLog" "Exception Occurred: $_.Exception`n"
            }
        }
        
        if ($addDateToFile -eq "FALSE") {
            Add-Content "$dailyLog" "`r`n"
            $addDateToFile = "TRUE"
        }
        
        get-childitem $weeklyBackup |? {$_.psiscontainer -and $_.lastwritetime -le ($currentDate).adddays(-28)} |% { 
            try {
                if ($addDateToFile -eq "TRUE") {
                    Add-Content "$weeklyLog" "$currentDate`r`n"
                    $addDateToFile = "FALSE"
                }
        
                $fullPath = $_.FullName
                remove-item $fullPath -Recurse -force
        
                if (test-path $fullPath) {
                    Add-Content "$weeklyLog" "FAILED TO DELETE $fullPath`n"
                } else {
                    Add-Content "$weeklyLog" "SUCCESSFULLY DELETED $fullPath`n"
                }
            }
            catch {
                Add-Content "$weeklyLog" "Exception Occurred: $_.Exception`n"
            }
        }
        
        if ($addDateToFile -eq "FALSE") {
            Add-Content "$weeklyLog" "`r`n"
            $addDateToFile = "TRUE"
        }
        
        get-childitem $monthlyBackup |? {$_.psiscontainer -and $_.lastwritetime -le ($currentDate).adddays(-365)} |% { 
            try {
                if($addDateToFile -eq "TRUE") {
                    Add-Content "$monthlyLog" "$currentDate`r`n"
                    $addDateToFile = "FALSE"
                }
        
                $fullPath = $_.FullName
                remove-item $fullPath -Recurse -force 
        
                if (test-path $fullPath) {
                    Add-Content "$monthlyLog" "FAILED TO DELETE $fullPath`n"
                } else {
                    Add-Content "$monthlyLog" "SUCCESSFULLY DELETED $fullPath`n"
                }
            }
            catch {
                Add-Content "$monthlyLog" "Exception Occurred: $_.Exception`n"
            }
        } 
        
        if ($addDateToFile -eq "FALSE") {
            Add-Content "$monthlyLog" "`r`n"
        }
        

        在此我进行了 3 次不同的备份(每天、每周和每月)。所以基本上我从一周前的每日,一个月前的每周和一岁的每月删除所有文件。我还将每个删除的日期和文件夹打印到文件中,或者在文件夹仍然存在或发生异常的情况下打印失败消息。然后每天运行此脚本,到目前为止运行良好。

        谢谢, 德曼

        【讨论】: