2

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

  1. Скопируйте целевые папки в каталог "Завершено"
  2. Обновление даты в исходных папках с использованием формата Previous Name_Today's Date (MMDDYY)
  3. Обновите дату файлов INDD в исходной папке, используя формат Current Name_Today's Date (MMDDYY)
  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 например.


Помощь будет принята с благодарностью!


Вот пример того, что скрипт должен делать

Копирует папку WHOLE в папку _OLD/Archive для каждого из них. Затем переименовывает папку и содержимое расширения на "текущую дату". Затем удаляет файлы .pdf и .vps только в новых каталогах даты.

Вот пример структуры папок.

Главный каталог:

Внутри одного из подкаталогов:

Единственное, что я пытаюсь переименовать - это папки MAIN с датами (после копирования), а затем файлы в подкаталоге.

Никакие другие папки не должны быть переименованы.

4 ответа4

3

Ниже я включил пакетный скрипт, который является своего рода гибридом, так как он использует 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 Logic

Примечание. Это только 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)

Easy Execute Примечание. Сохраните его в виде текстового файла с расширением .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"};                                                             
    }                                                                                                                              
};    

Дополнительные ресурсы

1

У меня есть решение PowerShell для вас.

archiver.ps1, archiver.bat и командная строка оболочки, чтобы запустить его. Поместите файл 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{}

Архиватор файлов.Летучая мышь (1 строка)

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

Вызов командной оболочки:

archiver c:\scripting\archiver LIFE_ ANNUAL_ _OLD

Или для запуска командного файла с двойным щелчком, просто введите параметры в командный файл следующим образом:

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

измените измененное значение "-Exclude $ archiveFolder" на "-File" во 2-й команде gci

изменить 2 - настроить два имени файла / папки, а также включить пакетный файл для «двойного щелчка» для запуска.

отредактируйте 3 замененных дня / месяца / года на месяц / день / год согласно предложению SimonS.

1

У меня также (наконец) есть решение PowerShell.

Вы должны создать профиль PowerShell и поместить в него функцию, представленную ниже. затем он будет готов к использованию при каждом запуске PowerShell.

Измените $Destination Path в блоке 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 }
            }
        }
    }
}

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

0

Используйте 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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .