【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 (
  // まだ存在しない
)

とまぁこんな感じです

おすすめ

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です