私の目標は、コピーを介してフォルダーを自動的にアーカイブし、元のフォルダーとその中のファイルの名前を現在の日付に変更してから、古い本番ファイルをクリーンアップするために使用できる.batを用意することです。
Previous Name_Today's Date
(MMDDYY)の形式を使用してソースフォルダーの日付を更新しますCurrent Name_Today's Date
(MMDDYY)の形式を使用して、ソースフォルダー内のINDDファイルの日付を更新します。私は初心者ですが、調査と情報源からこのコードをまとめました。
@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\""
がファイルの名前を変更するのに正しいかどうかわかりません。名前は、PO番号(6桁)、タイトル、アンダースコア、日付の順です。
たとえば、123456_Life_Kit_020819。
助けていただければ幸いです!
WHOLEフォルダーをそれぞれの_OLD/Archiveフォルダーにコピーします。次に、フォルダとコンテンツ拡張子の名前を「現在の日付」に変更します。次に、新しい日付ディレクトリの.pdfファイルと.vpsファイルのみを削除します。
これはフォルダ構造の例です。
メインディレクトリ:
サブディレクトリの1つ内:
名前を変更しようとしているのは、日付(コピー後)のあるMAINディレクトリフォルダーと、サブディレクトリ内のファイルだけです。
他のフォルダの名前を変更する必要はありません。
以下に、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のみですが、
$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"};
}
};
注:以下のスクリプトの上部にある相関変数(
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
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"};
}
};
/S :: copy Subdirectories, but not empty ones. /E :: copy subdirectories, including Empty ones. /XF file [file]... :: eXclude Files matching given names/paths/wildcards.
標準 エイリアス Foreachオブジェクトの場合:「
%
」シンボル、ForEach
'
?
'シンボルとWhereは、どちらもWhere-Objectのエイリアスです。 Where-Objectコマンドを明示的に実行する場合は、Where-objectまたは '?
'を実行します。
私はあなたのためのPowerShellソリューションを持っています。
archiver.ps1、archiver.bat、そしてシェルラインにそれを開始するように命令します。 PS1ファイルとBATファイルを同じフォルダー(選択した場所)に配置します。名前の変更は、アンダースコアと6桁の「_ ######」を目的としています。
BATファイルは4つのパラメータを取ります:
再帰検索のベースとなるルートフォルダ。
変更するファイル/フォルダ名のサブセクション例: "Annual_"
変更する2番目のファイル/フォルダー名サブセクション例: "Life_"
作成/追加するアーカイブフォルダの名前。例: "_ 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{}
File Archiver.Bat(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"
2番目のgciコマンドで編集が「-Exclude $ archiveFolder」を「-File」に変更
編集2- 2つのファイル/フォルダー名を調整し、「ダブルクリック」して実行するバッチファイルも含めます。
SimonSの提案に従って、3つの交換された日/月/年を月/日/年に編集します。
私も(ついに)PowerShellソリューションを手に入れました。
PowerShellプロファイルを作成 そしてその中に関数を配置する必要があります。これで、PowerShellを起動するたびに使用できるようになります。
Param()
ブロックの$Destination
パスを任意のバックアップ先パスに変更します。
関数の使用方法の例を次に示します。
# 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 }
}
}
}
}
また、保持するファイル拡張子を指定できるロジックを含めることもできます。さらに、必要に応じて、削除するファイル拡張子を指定することもできます。
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/
を参照)、Logwot8
を使用してWindowsにインストールできます。