使用logrotate

使用logrotate

我的目标是拥有一个 .bat,可以用来通过复制自动存档文件夹,使用当前日期重命名原始文件夹和其中的文件,然后清除旧的生产文件。

  1. 将目标文件夹复制到“完全的”目录
  2. Previous Name_Today's Date使用(MMDDYY)格式更新源文件夹的日期
  3. Current Name_Today's Date使用格式(MMDDYY)更新源文件夹中 INDD 文件的日期
  4. “干净的”删除源文件夹中的所有 .VPS 和 .PDF 文件

我是一个新手,但我根据研究和资料拼凑了这段代码:

@echo off
setlocal enabledelayedexpansion
for /f "skip=1" %%x in ('wmic os get localdatetime') do if not defined MyDate set MyDate=%%x
set today=%MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%
xcopy /s /e /q /y "G:\...\Annual_*" "G:\...\_DONE\"
xcopy /s /e /q /y "G:\...\Life_*" "G:\...\_DONE\"
MOVE "G:\...\Annual_*" "G:\...\Annual_today"
MOVE "G:\...\Life_today" "G:\...\Life_today"
FOR /M *.indd /C "cmd /c rename @file \"@fname - today.indd\""
del /s "G:\...\Annual_today" *.pdf
del /s "G:\...\Annual_today" *.vps
del /s "G:\...\Life_today" *.pdf
del /s "G:\...\Life_today" *.vps
"G:\...\New_Job.bat" > output.txt

我的最终目标是能够更改源文件夹和存档文件夹的目录路径,以便我可以将此脚本重复用于不同的客户端文件。


当前的问题

就目前情况而言,脚本不会复制和创建存档文件夹文件,只是从所有目录中删除所有 VPS 和 PDF 文件,而不仅仅是目标文件夹。

我不确定我是否正确执行了日期检查,然后将其用作变量来重命名未来的文件夹和文件。

我不知道FOR /M *.indd /C "cmd /c rename @file \"@fname - today.indd\""重命名文件是否正确。名称是采购订单号(6 位数字),然后是标题、下划线和日期。

例如 123456_Life_Kit_020819。


非常感谢您的帮助!


以下是脚本应执行的操作的示例

在此处输入图片描述

将整个文件夹复制到每个文件夹的 _OLD/Archive 文件夹中。然后将文件夹和内容扩展名重命名为“当前日期”。然后仅删除新日期目录中的 .pdf 和 .vps 文件。

这是文件夹结构的一个示例。

主目录:

在此处输入图片描述

在其中一个子目录内:

在此处输入图片描述

我尝试重命名的唯一内容是带有日期(复制后)的主目录文件夹以及子目录中的文件。

无需重命名其他文件夹。

答案1

我在下面包含了一个批处理脚本,它是一种混合脚本,因为它使用 PowerShell,但它动态地构建和执行它,但每个dest=变量值的存档目标用于相应的处理。

我确实使用了一种方法Robocopy排除您想要从目标/存档文件夹中递归删除的文件扩展名类型,这样它就不会不必要地复制,因此无需删除。

我使用了大量 PowerShell 命令,因此,我并没有列出所有命令,而是将其中一些包含在更多资源如果您想进一步了解,请参阅其他学习部分。

批处理脚本

笔记:只需根据下面脚本顶部的相关变量(、和)设置源、目标和排除文件,然后单击src=即可dest=运行。excludedFiles=

SET "src=G:\Folder\Production"
SET "dest=G:\Folder\__Archive"
SET "fname=*.*"
SET "excludedFiles=*.pdf *.vps"

Robocopy "%src%" "%fname%" "%dest%" /E /XF %excludedFiles%
CALL :PSScript

SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
CD /D "%PowerShellDir%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%'"
IF EXIST "%PSScript%" DEL /Q /F "%PSScript%"
EXIT

:PSScript
SET PSScript=%temp%\~tmp%~n0.ps1
IF EXIST "%PSScript%" DEL /Q /F "%PSScript%"

ECHO $Main ^= "%dest%";                                                                                                               >"%PSScript%"
ECHO $Today ^= ^(^("{0:MMddyy}" -f ^(get-date^).AddHours^(0^)^).ToString^(^)^)                                                        >>"%PSScript%"
ECHO $Folders ^= ^(Get-ChildItem -Directory $Main ^| ^? {$_ -match "([0-9]{6})"}^);                                                   >>"%PSScript%"

ECHO $Folders ^| %% {                                                                                                                 >>"%PSScript%"
ECHO If^($_ -match "([0-9]{6})"){                                                                                                     >>"%PSScript%"
ECHO         $root  ^= ^(Split-Path -path $_.Fullname^);                                                                              >>"%PSScript%"
ECHO         $oBase ^= ^(Split-Path -path $_.Fullname -leaf^);                                                                        >>"%PSScript%"
ECHO         $nBase ^= ^($oBase.Replace^($matches[1],$Today^)^);                                                                      >>"%PSScript%"
ECHO         Rename-Item "$root\$oBase" "$root\$nBase";                                                                               >>"%PSScript%"
ECHO     }                                                                                                                            >>"%PSScript%"
ECHO };                                                                                                                               >>"%PSScript%"

ECHO $Folders ^= ^(Get-ChildItem -Directory $Main ^| ^? {$_.Name -match "([0-9]{6})"}^).FullName;                                     >>"%PSScript%"
ECHO $Files   ^= ^($Folders ^| %% {Get-ChildItem "$_\*" -File -Include *.indd} ^| ^? {$_.Name -match "[0-9]{6}.*?([0-9]{6})"}^);      >>"%PSScript%"

ECHO $Files ^| %% {                                                                                                                   >>"%PSScript%"
ECHO If^($_.Name -match "[0-9]{6}.*?([0-9]{6})"^)                                                                                     >>"%PSScript%"
ECHO     {                                                                                                                            >>"%PSScript%"
ECHO         $x ^= $matches[1];                                                                                                       >>"%PSScript%"
ECHO         $root ^= ^(Split-Path -path $_.Fullname^);                                                                               >>"%PSScript%"
ECHO         $nName ^= ^($_.Name.Replace^($x,$today^)^);                                                                              >>"%PSScript%"
ECHO         If^(!^(Test-Path "$root\$nName"^)^){Rename-Item $_.FullName "$root\$nName"};                                             >>"%PSScript%"
ECHO     }                                                                                                                            >>"%PSScript%"
ECHO };                                                                                                                               >>"%PSScript%"
GOTO :EOF

PowerShell 逻辑

笔记:如果您想使用它,这是单独的 PowerShell,但您只需将$Main =变量值设置为文件夹和文件的存档文件夹路径,并mmddyy使用运行时使用当前日期的字符进行更新的字符串。

$Main = "G:\Folder\__Archive";                                                                                                                
$Today = (("{0:MMddyy}" -f (get-date).AddHours(0)).ToString())                                                          
$Folders = (Get-ChildItem -Directory $Main | ? {$_ -match "([0-9]{6})"});                                                   
$Folders | % {                                                                                                                    
If($_ -match "([0-9]{6})"){                                                                                                   
        $root  = (Split-Path -path $_.Fullname);                                                                                
        $oBase = (Split-Path -path $_.Fullname -leaf);                                                                          
        $nBase = ($oBase.Replace($matches[1],$Today));                                                                        
        Rename-Item "$root\$oBase" "$root\$nBase";                                                                                 
    }                                                                                                                              
};                                                                                                                                 
$Folders = (Get-ChildItem -Directory $Main | ? {$_.Name -match "([0-9]{6})"}).FullName;                                     
$Files   = ($Folders | % {Get-ChildItem "$_\*" -File -Include *.indd} | ? {$_.Name -match "[0-9]{6}.*?([0-9]{6})"});
$Files | % {                                                                                                                      
If($_.Name -match "[0-9]{6}.*?([0-9]{6})")                                                                                    
    {                                                                                                                              
        $x = $matches[1];                                                                                                         
        $root = (Split-Path -path $_.Fullname);                                                                                 
        $nName = ($_.Name.Replace($x,$today));                                                                                
        If(!(Test-Path "$root\$nName")){Rename-Item $_.FullName "$root\$nName"};                                                             
    }                                                                                                                              
};    

PowerShell 版本 2.0 兼容逻辑

批处理(PS 2.0)

笔记:只需根据下面脚本顶部的相关变量(、和)设置源、目标和排除文件,然后单击src=即可dest=运行。excludedFiles=

SET "src=G:\Folder\Production"
SET "dest=G:\Folder\__Archive"
SET "fname=*.*"
SET "excludedFiles=*.pdf *.vps"

Robocopy "%src%" "%fname%" "%dest%" /E /XF %excludedFiles%
CALL :PSScript

SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
CD /D "%PowerShellDir%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%'"
IF EXIST "%PSScript%" DEL /Q /F "%PSScript%"
EXIT

:PSScript
SET PSScript=%temp%\~tmp%~n0.ps1
IF EXIST "%PSScript%" DEL /Q /F "%PSScript%"

ECHO $Main ^= "%dest%";                                                                                                                                >"%PSScript%"
ECHO $Today ^= ^(^("{0:MMddyy}" -f ^(get-date^).AddHours^(0^)^).ToString^(^)^);                                                                        >>"%PSScript%"
ECHO $Folders ^= ^(Get-ChildItem $Main ^| ^? {^($_.PSIsContainer^) -and ^($_ -match "([0-9]{6})"^)}^);                                                 >>"%PSScript%"
ECHO $Folders ^| %% {                                                                                                                                  >>"%PSScript%"
ECHO If^($_ -match "([0-9]{6})"^){                                                                                                                     >>"%PSScript%"
ECHO         $root  ^= ^(Split-Path -path $_.Fullname^);                                                                                               >>"%PSScript%"
ECHO         $oBase ^= ^(Split-Path -path $_.Fullname -leaf^);                                                                                         >>"%PSScript%"
ECHO         $nBase ^= ^($oBase.Replace^($matches[1],$Today^)^);                                                                                       >>"%PSScript%"
ECHO         Rename-Item "$root\$oBase" "$root\$nBase";                                                                                                >>"%PSScript%"
ECHO     }                                                                                                                                             >>"%PSScript%"
ECHO };                                                                                                                                                >>"%PSScript%"
ECHO $Folders ^= ^(Get-ChildItem $Main ^| ^? {^($_.PSIsContainer^) -and ^($_ -match "([0-9]{6})"^)}^);                                                 >>"%PSScript%"
ECHO $Files   ^= ^($Folders ^| %% {Get-ChildItem $_.FullName -Recurse -Include *.indd ^| ^? {^(!$_.PSIsContainer^) -and ^($_.Name -match "[0-9]{6}.*?([0-9]{6})"^)}}^);>>"%PSScript%"
ECHO $Files ^| %% {                                                                                                                                    >>"%PSScript%"
ECHO If^($_.Name -match "[0-9]{6}.*?([0-9]{6})"^)                                                                                                      >>"%PSScript%"
ECHO     {                                                                                                                                             >>"%PSScript%"
ECHO         $x ^= $matches[1];                                                                                                                        >>"%PSScript%"
ECHO         $root ^= ^(Split-Path -path $_.Fullname^);                                                                                                >>"%PSScript%"
ECHO         $nName ^= ^($_.Name.Replace^($x,$today^)^);                                                                                               >>"%PSScript%"
ECHO         If^(!^(Test-Path "$root\$nName"^)^){Rename-Item $_.FullName "$root\$nName"};                                                              >>"%PSScript%"
ECHO     }                                                                                                                                             >>"%PSScript%"
ECHO };                                                                                                                                                >>"%PSScript%"      
GOTO :EOF

PowerShell(PS 2.0)

轻松执行注意事项:将其保存为带有扩展名的文本文件.ps1到文件夹中,然后G:\Folder\Archiver.ps1在 PowerShell 命令行中放置一个点、一个空格,然后用双引号括起来输入完整的脚本名称和路径,按 Enter

在此处输入图片描述

$Main = "G:\Folder\__Archive";                                                                                                                
$Today = (("{0:MMddyy}" -f (get-date).AddHours(0)).ToString());  
$Folders = (Get-ChildItem $Main | ? {($_.PSIsContainer) -and ($_ -match "([0-9]{6})")});

$Folders | % {                                                                                                                    
If($_ -match "([0-9]{6})"){                                                                                                   
        $root  = (Split-Path -path $_.Fullname);                                                                                
        $oBase = (Split-Path -path $_.Fullname -leaf);                                                                          
        $nBase = ($oBase.Replace($matches[1],$Today));                                                                        
        Rename-Item "$root\$oBase" "$root\$nBase";                                                                                 
    }                                                                                                                              
};   

$Folders = (Get-ChildItem $Main | ? {($_.PSIsContainer) -and ($_ -match "([0-9]{6})")});
$Files   = ($Folders | % {Get-ChildItem $_.FullName -Recurse | ? {(!$_.PSIsContainer) -and ($_.Name -match "[0-9]{6}.*?([0-9]{6})")}});

$Files | % {                                                                                                                      
If($_.Name -match "[0-9]{6}.*?([0-9]{6})")                                                                                    
    {                                                                                                                              
        $x = $matches[1];                                                                                                         
        $root = (Split-Path -path $_.Fullname);                                                                                 
        $nName = ($_.Name.Replace($x,$today));                                                                                
        If(!(Test-Path "$root\$nName")){Rename-Item $_.FullName "$root\$nName"};                                                             
    }                                                                                                                              
};    

更多资源

答案2

我(终于)有一个 PowerShell 解决方案。

你应该创建 PowerShell 配置文件并将下面的函数放入其中。这样,无论何时启动 PowerShell,它都可以使用。

$Destination将块中的路径更改Param()为您想要的任何备份目标路径。

以下是一些如何使用该函数的示例:

# This will backup the specified path to the default destination specified in the function
Backup-Folder "C:\install\TestApp"

# You can also Backup multiple paths at once
Backup-Folder "C:\install\TestApp","D:\somepath\xy_020317"

# You can also overwrite the destination where the folder should be backed up to
Backup-Folder "C:\install\TestApp" -Destination "G:\MyNewFavoriteBackupLocation"

# You can also overwrite the setting for what Extensions to delete
Backup-Folder "C:\install\TestApp" -DeleteExtensions ".xlsx",".docx",".pdf"

# You can combine all of the above to be as flexible as you'd like
Backup-Folder "C:\install\TestApp","D:\somepath\xy_020317" -Destination "E:\xy" -DeleteExtensions ".ai"

顺便说一句。从你的评论中我感觉,你想要一个批处理调用,通过将这个函数放在你的 PowerShell 配置文件中,你可以*.bat在任何你想要的地方(例如桌面或任何地方)创建一个文件,其中包含以下行:

powershell "Backup-Folder 'C:\foo\folder1', 'C:\bar\ANNUAL_323232', 'E:\somewhere'"

此功能将:

  • 备份整个文件夹到$Destination
  • $DeleteExtensions删除文件夹中所有具有指定扩展名的文件
  • 检查是否必须更改文件夹及其文件的名称,否则不重命名
  • 如果日期与之前不同,它将把文件夹和文件重命名为新日期
  • 如果文件没有日期,它会添加它

这是完整注释的函数:

function Backup-Folder {

    Param(
        [ValidateScript({ Test-Path $_ })]
        [string[]]$Path,
        [string]$Destination = "C:\install\_DONE",
        [string[]]$DeleteExtensions = @(".pdf",".vps")
    )

    # Creating Destination Directory if not already present
    mkdir $Destination -ErrorAction SilentlyContinue > $null

    # Getting the Date.
    $Date = (Get-Date).ToString("MMddyy")

    # Looping over each path
    foreach ($p in $path) {

        # Copy the whole folder to the destination
        Copy-Item $p $Destination -Recurse -Force

        # Get Folder Data
        $Folder = Get-Item $p 

        # Get Old and New Name
        $Folder.Name -match '\d{6}' > $null
        $Old = $Matches.GetEnumerator() | select -expand Value
        $New = if ($Old) { $Folder.Name -replace $Old,$Date } 
               else { "{0}_{1}" -f $Folder.Name,$Date }

        # if the Old Date is not the same as the new date Rename Folders and return them 
        # else return the original folder object
        $RenamedFolder = if ($Old -ne $Date) { Rename-Item $Folder -NewName $New -PassThru }
                         else { $Folder }

        # Get all Files in subfolder and loop over them
        # Add -Recurse after $RenamedFolder if you also want the script to go through 
        # all files of all subdirectories
        Get-ChildItem $RenamedFolder | ? { !$_.PsIsContainer } | foreach {

            # if the extension should be deleted, delete it
            if ($_.Extension -in $DeleteExtensions) {
                # Delete Item
                Remove-Item $_.FullName -Force
            }
            # else rename it.
            else {
                # Get Old and New Name
                $_.BaseName -match '\d{6}' > $null
                $OldName = $Matches.GetEnumerator() | select -expand Value
                $NewName = if ($OldName) { $_.Name -replace $OldName,$Date } 
                           else { "{0}_{1}{2}" -f $_.BaseName,$Date,$_.Extension }

                # Finally Rename Item if the Old Date is not the same as the new date
                if ($OldName -ne $Date) { Rename-Item $_.FullName -NewName $NewName }
            }
        }
    }
}

我们还可以添加一个逻辑来指定应该保留哪些文件扩展名,另外如果您认为有必要的话,还可以告诉您哪些文件扩展名应该被删除。

答案3

我有一个 powershell 解决方案给你。

归档器.ps1归档程序,然后使用命令 shell 行启动它。将 PS1 文件和 BAT 文件放在同一个文件夹中(您选择的任何位置)。重命名的目的是为了使用下划线和 6 位数字“_######”。

BAT文件有4个参数:

  1. 您希望递归搜索基于的根文件夹。

  2. 要修改的文件/文件夹名称子部分例如:“Annual_”

  3. 要修改的第二个文件/文件夹名称子部分示例:“Life_”

  4. 要创建/添加的存档文件夹的名称。例如:“_OLD”

文件Archiver.ps1:

Param(
     [Parameter(Position=0)] [string]$rootFolder = "C:\scripting\archiver"

     ,[Parameter(Position=1)] [string]$folderName1 = "ANNUAL_"

     ,[Parameter(Position=2)] [string]$folderName2 = "LIFE_"

     ,[Parameter(Position=3)] [string]$archiveFolder = "_OLD"
)
BEGIN
{

$today = get-date -UFormat %m%d%y

$folderName1 = "*"+$folderName1+"*"

$folderName2 = "*"+$folderName2+"*"

$startFolders = GCI -Path $rootFolder -Recurse -Include $folderName1, $folderName2 -Exclude $archiveFolder -Directory

pushd
foreach ($fold in $startFolders){
    cd $fold
    if(-not (Test-Path $archiveFolder)){md $archiveFolder | Out-Null}
    $theseFilez = gci -File
    if($theseFilez){
        foreach ($filez in $theseFilez){
            Copy-Item $filez $archiveFolder -Force
            if($filez -like "*.indd" -and $filez -notlike "*_$today*"){$filez | Rename-Item -NewName {$filez.Name -replace '[_]\d{6}',('_'+$today)}}
        }
    Remove-Item "*.pdf"
    Remove-Item "*.vps"
    }
    if($fold -notlike "*_$today*"){$fold | Rename-Item -NewName {$fold.Name -Replace '[_]\d{6}',('_'+$today)}}
}

popd

}

PROCESS{}
END{}

文件 Archiver.Bat(1 行)

start powershell -File Archiver.ps1 -rootFolder "%1" -folderName1 "%2" -folderName2 "%3" -archiveFolder "%4"

命令 Shell 调用:

archiver c:\scripting\archiver LIFE_ ANNUAL_ _OLD

或者对于双击运行的批处理文件,只需在批处理文件中输入参数,如下所示:

start powershell -File Archiver.ps1 -rootFolder "C:\scripting\archiver" -folderName1 "ANNUAL_" -folderName2 "LIFE_" -archiveFolder "_OLD"

编辑将第二个 gci 命令中的“-Exclude $archiveFolder”更改为“-File”

编辑 2 - 调整两个文件/文件夹名称,还包括用于“双击”运行的批处理文件。

按照 SimonS 的建议,编辑 3 将日/月/年替换为月/日/年。

答案4

使用logrotate

这正是它的用途......

配置文件logrotate.conf

/tmp/mydir/* {
    daily
    dateext
    olddir /tmp/myarchive
}

然后运行它。

touch /tmp/mydir/mylog1.txt /tmp/mydir/myotherlog2.txt
logrotate -vf ./logrotate.conf -s mystatus.logrotate

您应该在详细模式下看到类似这样的内容

reading config file ./logrotate.conf
olddir is now /tmp/myarchive
Reading state from file: mystatus.logrotate
Allocating hash table for state file, size 64 entries
Creating new state
Creating new state
Creating new state
Creating new state

Handling 1 logs

rotating pattern: /tmp/mydir/*  forced from command line (no old logs will be kept)
olddir is /tmp/myarchive, empty log files are rotated, old logs are removed
considering log /tmp/mydir/mylog1.txt
  Now: 2019-02-18 00:08
  Last rotated at 2019-02-18 00:00
  log needs rotating
considering log /tmp/mydir/myotherlog2.txt
  Now: 2019-02-18 00:08
  Last rotated at 2019-02-18 00:00
  log needs rotating
rotating log /tmp/mydir/mylog1.txt, log->rotateCount is 0
dateext suffix '-20190218'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
glob finding old rotated logs failed
renaming /tmp/mydir/mylog1.txt to /tmp/myarchive/mylog1.txt-20190218
disposeName will be /tmp/myarchive/mylog1.txt-20190218
removing old log /tmp/myarchive/mylog1.txt-20190218
rotating log /tmp/mydir/myotherlog2.txt, log->rotateCount is 0
dateext suffix '-20190218'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
glob finding old rotated logs failed
renaming /tmp/mydir/myotherlog2.txt to /tmp/myarchive/myotherlog2.txt-20190218
disposeName will be /tmp/myarchive/myotherlog2.txt-20190218
removing old log /tmp/myarchive/myotherlog2.txt-20190218

logrotate已在所有 Linux 系统上运行。它可能已在您的系统上运行(请参阅/etc/logrotate.conf/etc/logrotate.conf.d/),并且您可以在 Windows 上使用以下命令安装它:Logwot8

相关内容