【Script】階層構造をフラットにしてコピーする
今回の記事はタイトルのままなんですが、Windowsでファイルをコピーする処理をbatファイルで自動化する時に、重複があれば中止したかったのでそのためのbatファイルを作ってみました。
仕様
今回作成したbatファイルの仕様です
- 対象フォルダから再帰的にファイルを探し出してコピーする
- コピーの際に階層構造を維持しない
- 最初に重複した時点でエラーとして処理を終了する
BATファイルの中身
rem ERROR LEVEL set OPERATION_SUCCEEDED=0 set NO_SOURCCE_EXIST=1 set BASEDIR_NOT_FOUND=2 set FILE_ALREDY_EXIST=3 set COPY_COMMAND_FAILED=4 rem Copy Source set srcDir=D:\FileOperation\src rem Copy Destination set dstDir=D:\FileOperation\dst rem Check BaseDir existence if not exist %srcDir% exit /b %BASEDIR_NOT_FOUND% rem Check Source existence dir /s /b /a:-d "%srcDir%" > nul if %ERRORLEVEL% == 1 ( exit /b %NO_SOURCCE_EXIST% ) rem Copy for /F %%i in ('dir /s /b /a:-d "%srcDir%"') do ( echo %%~nxi echo %%i echo "%dstDir%\%%~nxi" rem Check file existence in dst if exist "%dstDir%\%%~nxi" ( echo "%%~nxi is already exist in %dstDir%" exit /b %FILE_ALREDY_EXIST% ) else ( echo "copy %%i to %dstDir%\%%~nxi" copy %%i %dstDir% if %ERRORLEVEL% == 1 ( exit /b %COPY_COMMAND_FAILED% ) ) ) exit /b OPERATION_SUCCEEDED
まずは全体の処理をば
では、それぞれ順を追って解説していきます
ベースディレクトリの確認
今回、dir
コマンドを利用してファイルの中身を再帰的に取得します。その際に存在しないフォルダを指定してしまうと処理が帰ってこないようになっています。そのためまずはベースフォルダが存在するかどうかを確認する必要があります。
rem Check BaseDir existence if not exist %srcDir% exit /b %BASEDIR_NOT_FOUND%
コピー対象の存在確認
続いて、ベースフォルダ内にファイルが存在するかどうかを確認しなければなりません。というのも、最終的にfor
文を利用してコピーを行うのですが、この際に空のリストを指定すると文法エラーになってしまいます。これを確認するためには、実際にdir
コマンドを実行してその結果を%ERRORLEVEL%
で確認します。
rem Check Source existence dir /s /b /a:-d "%srcDir%" > nul if %ERRORLEVEL% == 1 ( exit /b %NO_SOURCCE_EXIST% )
ファイルリストでループ処理
batのfor
文は、コマンドの実行結果を元にしてループ処理を行うことができます。以下の例では、dir
コマンドの実行結果を変数i
に逐一代入してループしています。
for /F %%i in ('dir /s /b /a:-d "%srcDir%"') do ( //do something )
コピー先の存在確認
最後に、現在処理しているファイルがコピー先に存在しているかどうかを確認します。この時、処理中のファイルのファイル名を取得するには%%~nxi
とします。~n
が拡張子抜きのファイル名の取得、~x
が拡張子を取得するので、これらを組み合わせて拡張子付きのファイル名が取得できます。
echo "%dstDir%\%%~nxi" if exist "%dstDir%\%%~nxi" ( // 既に存在している ) else ( // まだ存在しない )
とまぁこんな感じです
最近のコメント