2017-12-20 8 views
0

バックアップシステムは毎日.bakファイルを作成し、問題が発生した場合にファイルを復元することができます。残しておくと、これらのファイルは私たちのストレージにいっぱいになるので、新しいバッチファイルが作成された後、毎日古いバッチファイルを削除するために実行できるバッチファイルが見つかりました。より若いファイルが存在する場合にのみファイルを削除するバットファイル

forfiles -p "c:\xxx\yyy" -s -m *.bak /D -2 /C "cmd /c del @path"

これはうまく動作しますが、私たちのバックアップシステムに障害が発生し、新しい.BAKファイルが古いの.bakファイルの代わりにそこに滞在するに作成されていない何らかの理由であれば、私はそのようセーフティネットを作成したいですインシデント発生時にはバックアップファイルが残っていません。理想的には、私は1日より若い.bakファイルをチェックするものがほしいと思っています。これらのファイルが存在しない場合、上記の行は実行されませんが、若いファイルが存在すれば、上記の行が実行され、古いファイルが削除されます。これがバッチファイルで可能かどうかは不明です。これについてあなたの助けを前にありがとう。

編集:私が必要とするものについてさらに詳しい情報があります。毎日午後10時頃約50回のバックアップ.bakファイルが作成され、c:¥xxx¥yyy というファイルに作成されます。これらのファイルは非常に大容量ですので、毎日自動的に実行されるバッチファイルを設定しています.日。これは普段の使用には問題ありませんが、バックアップシステムが何らかの理由でファイル.bakを作成しないと、私の頭の中にあるシナリオはどうなりますか?バッチファイルをチェックして、古いファイルを削除する前に新しい.bakファイルが作成されていることを確認します。基本的にバッチファイルを使用する方法は、1日より古いフォルダに特定のファイルタイプがあるかどうかをチェックする方法です。結果に応じてバッチファイルの内容を変更することができます。

これは、18日と19日に作成されたファイルの例です。

彼らはすべて、以下の形式に従うように見える
2004 Apr_backup_2017_12_18_210001_2986007.bak 
2004 Apr_backup_2017_12_19_210001_3168635.bak 
Subscribers_backup_2017_12_19_210003_3012893.bak 
model_backup_2017_12_19_210003_2544131.bak 

[DESC]_backup_[YEAR]_[MONTH]_[DAY]_21000[1/2/3]_[7 DIGIT NO.].bak 
+0

毎日** .bakファイル**を作成するバックアップシステムを持っているので、セーフティネットは必要ありません。私が示唆していることは、あなたの質問を読者の視点から言い換えようとすることです。 – Compo

+0

バックアップシステムが毎日1つのバックアップファイルを作成すると仮定すると、最後の2つのバックアップファイルは常に保持されます。 – Squashman

+0

あなたのご意見ありがとうございます@Compo、私はより明確にするために投稿を歓迎しました。 – HyperHook

答えて

0

私は、すべてのバックアップファイル名に[DESC]文字列の未知のリストは、バッチファイルで扱うことが最も難しいと思います。コードは、以下に示すようにこのリストを知ることで非常に簡単です。少なくとも、バッチファイル処理で重要な文字が含まれていないかどうかを知ることで、!%=のようになります。

しかし、ファイル名に特殊文字を[DESCR]文字列の未知のリストのためのコーディングの課題は、私にとって興味深いものだったので、私は、最初のバッチファイルのコメント次の開発:

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 
set "BackupFolder=C:\xxx\yyy" 

rem Search for files matching the wildcard pattern *_backup_*.bak in backup 
rem folder, assign each file name without file extension to environment 
rem variable FileName and call the subroutine GetUniqueDescs to get the 
rem file description at beginning of each file name into a list in memory. 

for /F "delims=" %%I in ('dir "%BackupFolder%\*_backup_*.bak" /A-D /B /ON 2^>nul') do (
    set "FileName=%%~nI" 
    call :GetUniqueDescs 
) 

rem Run command SET with FileDesc: to output all environment variables 
rem starting with that string in name and sorted by name and process 
rem this list whereby each line ends with =1 as value 1 is assigned 
rem to each of these environment variables. 

rem For each unique file description in output list assign the file 
rem description with =1 appended to environment variable FileDesc 
rem and run subroutine DeleteFiles. 

for /F "tokens=2 delims=:" %%I in ('set FileDesc: 2^>nul') do (
    set "FileDesc=%%I" 
    call :DeleteFiles 
) 

rem Restore initial environment on starting this batch file and exit it. 
endlocal 
goto :EOF 


rem The subroutine GetUniqueDescs first runs a string substitution which 
rem gets the backup pattern part from file name, i.e. everything in file 
rem name from _backup_ to end of file name. 

rem Then another string substitution is used to remove this string from 
rem current file name to get just the description and define an environment 
rem variable of which name starts with FileDesc: and ends with the file 
rem description. The value assigned to this environment variable is 1. 

:GetUniqueDescs 
set "BackupPart=%FileName:*_backup_=_backup_%" 
call set "FileDesc:%%FileName:%BackupPart%=%%=1" 
goto :EOF 


rem The subroutine DeleteFiles removes first from passed file description 
rem the last two characters being always =1 from list of environment 
rem variables starting with FileDesc: and appends the backup wildcard 
rem pattern. 

rem Command DIR is used to find all files in backup folder starting 
rem with current file description and _backup_ and output the found 
rem files sorted by last modification date with newest modified file 
rem first and oldest modified file last. 

rem The command FOR processing this list skips the first file name 
rem output by DIR which means the newest file. All other, older 
rem files perhaps also found by DIR are deleted one after the other. 

:DeleteFiles 
set "FilePattern=%FileDesc:~0,-2%_backup_*.bak" 
for /F "skip=1 delims=" %%J in ('dir "%BackupFolder%\%FilePattern%" /A-D /B /O-D /TW') do ECHO del "%BackupFolder%\%%J" 
goto :EOF 

コマンドの最後が、1つでECHOコマンド前の行delは、実際にファイルを削除するのではなく、削除されるファイルを表示するだけです。

最後に1行のオプションskip=1を指定すると、常に1つのバックアップファイルが保持されます。

例えば、skip=5を使用すると、最終更新日に従って最新の5つのファイルを通常バックアップファイルに作成し、作成日と他のすべてのファイルを削除します。

なバックアップの削除戦略の利点は、それは問題ではないということです。

  1. 特定のバックアップが作成される頻度 - 毎日、毎週または毎月;
  2. 最後のバックアップ作成がまったく成功した場合。
  3. 一部またはすべてのバックアップファイルが手動で削除された場合。
  4. 個々のバックアップファイルの保存期間。
  5. バックアップファイル削除のバッチファイルの実行頻度。

バックアップの削除に本当に重要なのは、各バックアップに必要な記憶領域と、削除処理後の空き領域の量です。バックアップファイルのファイル日付は空き容量を制限していません。残りのすべてのバックアップファイルのファイルサイズとバックアップメディア上の合計ストレージサイズは、実際に重要な要素です。だからこそ私はこれらの "古いものよりも古いものを削除する"すべてのことを理解していません。新しいファイルのための十分な空き領域がある限り、ファイルの年齢を気にする必要があるのは誰ですか?

最後に1行に/TWの代わりに/TCを使用すると、ファイルの作成日を使用することもできます。しかし、ファイルの作成日とは、ファイルがそのディレクトリに作成された日付であり、ファイル自体は作成されていません。そのため、ファイルの作成日は、ファイルが初めて作成されてから別のディレクトリにコピーまたは移動されたことがない場合にのみ有効です。

私は、ファイルを次のように、このバッチファイルをテストした:

C:\xxx\yyy\2004 !Apr_backup_2017_12_18_210001_2986007.bak 
C:\xxx\yyy\2004 !Apr_backup_2017_12_19_210001_3168635.bak 
C:\xxx\yyy\model%_backup_2017_12_19_210003_2544131.bak 
C:\xxx\yyy\model%_backup_2017_12_20_210003_2544131.bak 
C:\xxx\yyy\Subscribers=_backup_2017_12_19_210003_3012893.bak 
C:\xxx\yyy\Subscribers=_backup_2017_12_20_210003_3012893.bak 

、各ファイルの最終更新日時はファイル名に日付と一致しました。

バッチファイルの出力がされた:

del "C:\xxx\yyy\2004 !Apr_backup_2017_12_18_210001_2986007.bak" 
del "C:\xxx\yyy\model%_backup_2017_12_19_210003_2544131.bak" 
del "C:\xxx\yyy\Subscribers=_backup_2017_12_19_210003_3012893.bak" 

予想される結果です。各ファイルペアの古いファイルは削除されます。


は、それから私は、ファイル名の[DESC]一部は、ファイル拡張子なしでファイル名の残りの部分として容易に行うことができる得ることが33文字の固定長であると思いました。バッチファイルはECHOもを含む

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 
set "BackupFolder=C:\xxx\yyy" 

rem Search for files matching the long wildcard pattern 
rem *_backup_????_??_??_??????_???????.bak 
rem in backup folder and assign each file name without 
rem file extension to environment variable. 

rem The last 33 characters are removed from each file name to get the 
rem file description part at beginning of each file name. Then define 
rem an environment variable of which name starts with FileDesc: and 
rem ends with the file description. The value assigned to this 
rem environment variable is 1. 

for /F "delims=" %%I in ('dir "%BackupFolder%\*_backup_????_??_??_??????_???????.bak" /A-D /B /ON 2^>nul') do (
    set "FileName=%%~nI" 
    call set "FileDesc:%%FileName:~0,-33%%=1" 
) 

rem Run command SET with FileDesc: to output all environment variables 
rem starting with that string in name and sorted by name and process 
rem this list whereby each line ends with =1 as value 1 is assigned 
rem to each of these environment variables. 

rem For each unique file description in output list assign the file 
rem description with =1 appended to environment variable FileDesc 
rem and run subroutine DeleteFiles. 

for /F "tokens=2 delims=:" %%I in ('set FileDesc: 2^>nul') do (
    set "FileDesc=%%I" 
    call :DeleteFiles 
) 

rem Restore initial environment on starting this batch file and exit it. 
endlocal 
goto :EOF 


rem The subroutine DeleteFiles removes first from passed file description 
rem the last two characters being always =1 from list of environment 
rem variables starting with FileDesc: and appends the backup wildcard 
rem pattern. 

rem Command DIR is used to find all files in backup folder starting 
rem with current file description and _backup_ and output the found 
rem files sorted by last modification date with newest modified file 
rem first and oldest modified file last. 

rem The command FOR processing this list skips the first file name 
rem output by DIR which means the newest file. All other, older 
rem files perhaps also found by DIR are deleted one after the other. 

:DeleteFiles 
set "FilePattern=%FileDesc:~0,-2%_backup_*.bak" 
for /F "skip=1 delims=" %%J in ('dir "%BackupFolder%\%FilePattern%" /A-D /B /O-D /TW') do ECHO del "%BackupFolder%\%%J" 
goto :EOF 

は最後にdelを指令する左が、1本のラインは、バックアップフォルダ内の6つのファイルに同じ結果を生成します。

バッチファイルがファイル名の一部に存在する可能性のある文字を認識せずにさらに最適化できるかどうかはわかりません。私は可能なさらなる最適化について考えなかった。


よく知られており、ハードバッチファイルに記述することができ、たとえば2004 !Aprため、model%と私のテストケースで6つのファイル用Subscribers=私たちはユニークな[DESC]文字列のリストを想定してみましょう:

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 
set "BackupFolder=C:\xxx\yyy" 
for %%I in ("2004 !Apr" "model%%" "Subscribers=") do for /F "skip=1 delims=" %%J in ('dir "%BackupFolder%\%%~I*_backup_*.bak" /A-D /B /O-D /TW 2^>nul') do del "%BackupFolder%\%%J" 
endlocal 

最後に1行にECHOが存在しないため、このバッチファイルは実際にファイルを削除します。

はい、個別のバックアップファイル名を知っていると、すべての作業がはるかに簡単になります。

バッチファイルが1つでもコマンドラインに最適化することができます。

@for %%I in ("2004 !Apr" "model%%" "Subscribers=") do @for /F "skip=1 delims=" %%J in ('dir "C:\xxx\yyy\%%~I*_backup_*.bak" /A-D /B /O-D /TW 2^>nul') do @del "C:\xxx\yyy\%%J" 

最後は、私たちが作成されたバックアップストレージメディアに想定してみましょう:

  1. マシン全体のバックアップファイル名はComputerName_backup_YYYY_MM.tibで、3か月ごとに200 GiBと膨大なものがあり、バックアップ用のメディアに最後のバックアップのみがあれば十分です。
  2. 毎週土曜日にファイル名Folder_backup_YYYY_MM_DD.zipで更新されないファイルを含むフォルダのバックアップは、過去4週間の復元に十分な記憶メディアで約400MBを占めます。
  3. 毎日ファイル名がDatabase_backup_YYYY_MM_DD.bakのデータベースファイルをバックアップします。これは、1回のバックアップにつき20 MiBですが、データベースファイルでは一般的なものとほぼ同じように増加しています。最後の7日間。

必要な最低限のストレージメディアのサイズは次のとおりです。

(1+1) × 200 GiB + (4+1) × 400 MiB + (7+1) × (20×3) MiB 

1のTiBのストレージメディアのサイズが増上のデータベースのバックアップの成長速度に応じて、およそ次の3年間は本当に十分です係数3はすでに計算に含まれています。

単一の単純なバッチファイルを使用してバックアップファイルの管理を簡単に保つために、毎日のデータベースバックアップの作成で不要になったすべてのバックアップファイルを削除することをお勧めします。

@echo off 
set "BackupFolder=C:\xxx\yyy" 
call :DeleteBackups 1 "ComputerName" 
call :DeleteBackups 4 "Folder" 
call :DeleteBackups 7 "Database" 
goto :EOF 

:DeleteBackups 
for /F "skip=%1 delims=" %%I in ('dir "%BackupFolder%\%~2*_backup_*" /A-D /B /O-D /TW 2^>nul') do del "%BackupFolder%\%%I" 
goto :EOF 

不要なバックアップを削除することは、適切な戦略について考える上で非常に簡単です。使用するコマンドを理解し、どのように彼らは、コマンドプロンプトウィンドウを開き、そこに次のコマンドを実行し、完全にページが非常に慎重に、各コマンドのために表示されているすべてのヘルプを読んで、仕事のため


  • call /?
  • del /?
  • dir /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • rem /?
  • set /?
  • setlocal /?

も読む2>nulの説明についてUsing Command Redirection Operatorsに関するMicrosoftの記事。リダイレクト演算子>は、別のコマンド・プロセスに組み込まれたdirコマンドラインを実行するためのコマンドを実行する前に、このコマンドラインが始まったときに、Windowsのコマンドインタプリタプロセスリテラル文字として解釈さコマンドライン用のにキャレット文字^でエスケープする必要がありますバックグラウンドで

+0

完璧に動作する@Mofiありがとうございます。私は特にいくつのバックアップを保存するかをカスタマイズするのが好きです。ちょっとしたことの一つです。ファイルの保存期間をチェックする必要はありません。私が言いたいのは、サブフォルダも検索したいのであれば、コマンドの中で '/ b 'の隣に'/s'を追加するだけです。 – HyperHook

+0

サブフォルダでも検索するには '/ S'オプションを指定する必要がありますにも指定されています__DIR__コマンドライン。しかし、__DIR__が '/ S'で出力されるのは、ファイル拡張子の付いたファイル名だけでなく、フルパスで出力されている点にも注意してください。したがって、コマンド__DEL__は、 '/ S 'とともに__DIR__を使用する場合、' '%BackupFolder%\' 'を指定しないでください。 – Mofi

0

ここでは、限り、あなたは[DESC]_を含むファイル名を持っていないように動作するはずですテストされていないスクリプトの例です=または他の問題のある文字。

@Echo Off 
SetLocal DisableDelayedExpansion 
For /F "Delims==" %%A In ('Set _[ 2^>Nul') Do Set "%%A=" 
If /I Not "%CD%"=="C:\xxx\yyy" (Set "_[:]=T" 
    PushD "C:\xxx\yyy" 2>Nul||Exit /B) 
For /F "Tokens=1* Delims=_" %%A In ('Dir /B /O-N *_backup_*_*_*_*_*.bak' 
) Do If Defined _[%%A] (Del /A /F "%%A_%%B") Else Set "_[%%A]=T" 
If Defined _[:] PopD 
EndLocal 
Exit /B 
関連する問題