この記事では、バッチファイルにドロップした複数のフォルダを新規フォルダへコピーする方法についてご説明します。
なお、今回のバッチファイルは、フォルダをコピーする際は、指定した拡張子のファイルだけをコピーする指定をコードに盛り込みます。
【バッチファイル】バッチファイルにドロップした複数のフォルダを新規フォルダへコピーするには(指定した拡張子のファイルを除外)
指定した拡張子だけをコピーする指定をコードに盛り込むことで、フォルダをバッチファイルにドロップした際、バッチファイル実行後はその指定した拡張子のファイルだけコピーされます。
例えば、拡張子が「txt」「csv」のファイルだけコピーするよう指定しておくと、フォルダ配下にある拡張子が「txt」「csv」のファイルだけを対象にフォルダをコピーします。(「txt」「csv」以外のファイルはコピーしない)
今回紹介するバッチファイルの処理の大まかな流れは次の通りです。
なお、今回作成する新規フォルダの名前は、「バックアップ_年月日時分秒」(※例:バックアップ_20240107120938)とします。
新規フォルダは、フォルダ名が重複しないよう一意の名前で生成することが狙いです。
フォルダをコピーする際は指定した拡張子のファイルだけをコピーします。
ちなみに、記事タイトルに「複数のフォルダ」としてはいますが、単一のフォルダにも対応しています。
【動画】(指定した拡張子のファイルを除外して)バッチファイルにドロップした複数のフォルダを新規フォルダへコピーする実際の動き
本題に入る前に、まずは次の動画をご覧ください。
注意
今回紹介するバッチファイルはフォルダをコピーするので、大事なファイルを上書きしてしまったり、フォルダが生成されるなど、パソコン内のディレクトリ環境を変えてしまう場合があります。
バッチファイルを実行する前は、必ずコピー先の指定に十分お気を付けください。
その点を留意して自己責任でお使いいただければ幸いです。
フォルダの例
「C:¥work¥10_勉強¥17_バッチファイル¥0009¥from」配下のフォルダに、「data」「file」「xyz 2023」というフォルダが存在しています。
今回はこの「data」「file」「xyz 2023」の3つのフォルダをバッチファイルにドロップすると、「C:¥work¥10_勉強¥17_バッチファイル¥0009¥to」配下に新規フォルダを作成してその中にドロップしたフォルダをコピーします。
バッチファイルが作成する新規フォルダ(サンプル)は下のとおりです。
新規フォルダには、「バックアップ_年月日時分秒」(※例:バックアップ_20240107120938)の名前が付けられます。
なお、今回のバッチファイルのサンプルでは、拡張子が「txt」「csv」のファイルは除外するよう指定します。
今回はバッチファイルにドロップするフォルダを3つ用意しました。
「data」「file」「xyz 2023」のフォルダには下のファイルとフォルダが格納されています。
①「data」
②「file」
③「xyz 2023」
今回紹介するバッチファイルにフォルダをドロップして実行させると、指定したコピー先に新規フォルダが作成され、その新規フォルダ配下に「data」「file」「xyz 2023」全てフォルダがコピーされます。
コピーされた「data」「file」「xyz 2023」それぞれのフォルダ配下は下のとおりです。
①「data」
②「file」
③「xyz 2023」
各フォルダ配下を見てみると、拡張子が「txt」「csv」のファイルはコピーされず、拡張子が「txt」「csv」以外のファイル全てがコピーされています。
コードの例
@echo off rem コピー先のフォルダを指定する set copyToParent=C:\work\10_勉強\17_バッチファイル\0009\to rem 遅延環境変数展開を有効にする setlocal enabledelayedexpansion rem 現在の年月日時分秒を取得する for /f "tokens=1 delims=." %%a in ('wmic os get localdatetime ^| find "."') do set datetime=%%a rem 新規作成するフォルダの名前を取得する set newFolder=%copyToParent%\バックアップ_%datetime% rem 新しいフォルダを作成する mkdir "%newFolder%" rem 指定された各フォルダに対して繰り返して処理を行うFor文 for %%i in (%*) do ( rem ドラッグされた各フォルダをコピーする robocopy "%%~i" "%newFolder%\%%~ni" /E /IF *.txt /IF *.csv ) rem setlocalコマンドによって変更されたローカル環境変数の設定を元に戻す endlocal
注目すべきコード①
最初に見て頂きたいのは4行目です。
rem コピー先のフォルダを指定する set copyToParent=C:\work\10_勉強\17_バッチファイル\0009\to
以上のコードは、コピー先のフォルダパスを取得するコードです。
バッチファイルにフォルダをドロップしてそのフォルダをコピーする先のフォルダパスを指定します。
注目すべきコード②
次に見て頂きたいのは7行目です。
rem 遅延環境変数展開を有効にする setlocal enabledelayedexpansion
コードの説明
以上のコードは、遅延環境変数展開を有効にする処理のコードです。
変数の値を変更する場合に、その変更がすぐに反映されない場合があります。
今回のコードではFor文の中で何度か変数への値の格納処理が行われるので、この遅延環境変数展開を有効にする必要があります。
注目すべきコード③
次に見て頂きたいのは10行目です。
rem 現在の年月日時分秒を取得する for /f "tokens=1 delims=." %%a in ('wmic os get localdatetime ^| find "."') do set datetime=%%a
コードの説明
以上のコードは、現在の年月日時分秒を取得する処理のコードです。
コードの詳細
①for、in、do
forはコマンドで、処理を繰り返すコマンドです。
For文はinとdoを組み合わせて使います。
inはFor文の構文の一部で、inの後にはループ処理の対象を指定します。
doもFor文の構文の一部で、doの後に指定されたコマンドを実行します。
②/f
「/f」はforコマンドのオプションです。
「/f」オプションはファイルまたはコマンドの実行結果を変数に読み込むときに使います。
今回はコマンド(wmic os get localdatetime)の実行結果を扱うので、「/f」オプションを使います。
③tokens=1
「tokens=1」は「wmic os get localdatetime」コマンドが返す値に対し、区切り文字で分けられる1番目の文字列の指定を表します。
もし「tokens=2」なら2番目の文字列の指定を表します。
今回は年月日時分秒が欲しいので、「tokens=1」を指定しています。
④delims=.
「delims=.」は、区切り文字に「.」を指定する設定です。
「delims=」に「.」を結合させることで、「.」を区切り文字に指定することができます。
「wmic os get localdatetime」は現在の年月日時分秒を取得しますが、取得した値には、今回欲しい年月日時分秒以外に余計な文字列が含まれています。
今回欲しい年月日時分秒は「.」よりも前の文字列なので、「.」を区切り文字に指定して年月日時分秒だけを取得します。
「delims=.」を指定することで年月日時分秒だけを取得することができます。
⑤%%a
%%aは、inの後ろのコマンドが実行された後に、「.」を区切り文字として取得した1つ目のトークンの値を格納する変数です。
%%aの中の値は下のとおりです。
「.」を区切り文字に指定して取得された1つ目のトークの値である年月日時分秒の値が%%aに格納されています。
⑥wmic os get localdatetime
「wmic os get localdatetime」は現在のコンピュータのローカル日時を取得します。
「wmic os get localdatetime」だけ実行した結果は下のとおりです。
⑦^|
「^|」は、「wmic os get localdatetime」のコマンドと、「find “.”」のコマンドを連結させるものです。
「^|」を使って連結させることで、1行で「wmic os get localdatetime」と「find “.”」のコマンドを実行することができます。
順番は「wmic os get localdatetime」のコマンドを実行して次に「find “.”」のコマンドを実行します。
また、「|」の前に「^」(キャレット)を記述しているのは、「^」が無いと「|」が機能しないからです。
なので、「|」だけでなく「^」も記述しています。
⑧find “.”
「find “.”」は、対象から「.」の文字を検索するコマンドです。
今回は「wmic os get localdatetime」のコマンドが返す値から「.」の文字が含まれるデータを検索します。
「wmic os get localdatetime」のコマンドを実行した結果が下のとおりです。
「wmic os get localdatetime」のコマンドは、
「LocalDateTime」と「20240108153907.629000+540」の2行の値を返します。
このうち、2行目の「20240108153907.629000+540」が現在のコンピュータのローカル日時ですが、コンピュータのローカル日時には「.」の文字が含まれます。
年月日時分秒の値が含まれる「20240108153907.629000+540」の値だけが欲しいので「find “.”」コマンドを実行してこのコンピュータのローカル日時を取得します。
⑨set datetime=%%a
「set datetime=%%a」は%%aの値をdatetimeに格納する処理です。
注目すべきコード④
次に見て頂きたいのは13行目です。
rem 新規作成するフォルダの名前を取得する set newFolder=%copyToParent%\バックアップ_%datetime%
コードの説明
以上のコードは、新規作成するフォルダの名前を取得する処理のコードです。
今回作成する新規フォルダの名前は、「バックアップ_年月日時分秒」(※例:バックアップ_20240107120938)とします。
なので、「バックアップ_」の文字列と、年月日時分秒が格納された変数datetimeの値を結合させます。
注目すべきコード⑤
次に見て頂きたいのは16行目です。
rem 新しいフォルダを作成する mkdir "%newFolder%"
コードの説明
以上のコードは、新しいフォルダを作成する処理のコードです。
フォルダを新規作成する場合はmkdirコマンドを実行します。
mkdirコマンドの引数には、新規作成するフォルダのフルパスを指定します。
注目すべきコード⑥
次に見て頂きたいのは19行目です。
rem 指定された各フォルダに対して繰り返して処理を行うFor文 for %%i in (%*) do (
コードの説明
以上のコードは、ドロップされたフォルダの数だけ処理を繰り返すfor文です。
今回の例では3つのフォルダをバッチファイルにドロップしますが、ドロップするフォルダの数が3つなので、3回処理を繰り返します。
①%%i
バッチファイルにドロップされたフォルダが代入されます。
②in
INはFor文とセットで使う構文で、INの後にバッチファイルにドロップされたフォルダ全てが指定されます。
③%*
%*には、バッチファイルにドロップされたフォルダ全てが格納されます。
④do
doはFor文とセットで使う構文です。
注目すべきコード⑦
次に見て頂きたいのは22行目です。
rem ドラッグされた各フォルダをコピーする robocopy "%%~i" "%newFolder%\%%~ni" /E /IF *.txt /IF *.csv
コードの説明
以上のコードは、robocopyコマンドを実行して、バッチファイルにドロップされたフォルダをコピー先にコピーする処理のコードです。
また、「/IF」オプションを使い、コピーする対象のファイルの拡張子を指定します。
以上のコードでは「/IF」オプションに「txt」と「csv」を指定していますが、robocopyコマンドが実行されると拡張子が「txt」と「csv」のファイルがコピーされます。
第1引数:”%%~i”
第1引数である「”%%~i”」には、バッチファイルにドロップされたフォルダのフルパスが格納されています。
以下の画像だと、「C:¥work¥10_勉強¥17_バッチファイル¥0009¥from」配下の「data」「file」「xyz 2023」の3つのフォルダがバッチファイルにドロップされたので、「”%%~i”」には「data」「file」「xyz 2023」のうち「C:¥work¥10_勉強¥17_バッチファイル¥0009¥from¥data」の文字列(フルパス)が格納されます。
ちなみに「”」(ダブルクォーテーション)で囲っているのは、スペースを含むフォルダ名を認識させるためです。
フォルダ名にスペースが含まれていると、スペースの前後で2つの引数として認識されてしまうため、「”」(ダブルクォーテーション)で囲むことで1つの引数として認識させることができます。
第2引数:”%newFolder%¥%%~ni”
第2引数である「”%newFolder%¥%%~ni”」には、コピー先のパスが格納されています。
例えば「C:¥work¥10_勉強¥17_バッチファイル¥0009¥from」配下の「data」のフォルダがドロップされた場合、「”%newFolder%¥%%~ni”」には、「C:¥work¥10_勉強¥17_バッチファイル¥0009¥to¥バックアップ_20240108173829¥data」の文字列が格納されます。
※「20240108173829」は現在のコンピュータのローカル日時
「”%newFolder%¥%%~ni”」だと分かりづらいので、下のとおりに分解してみます。
- %newFolder%:新規作成したフォルダ
- ¥:パスの区切り文字「¥」
- %%~ni:ドロップされたフォルダのパスの最下層のディレクトリ
①%newFolder%
「%newFolder%」は、新規作成したフォルダです。
今回の例では、copyToに「C:¥work¥10_勉強¥17_バッチファイル¥0009¥to¥バックアップ_20240108173829」が格納されています。
②¥
「¥」はパスの区切り文字です。
③%%~ni
「%%~ni」は第1引数の「%%~i」に格納された、バッチファイルにドロップされたフォルダのフルパスの最下層ディレクトリです。
例えば「C:¥work¥10_勉強¥17_バッチファイル¥0009¥from」配下の「data」のフォルダがドロップされた場合、「%%~ni」には「data」の文字列が格納されます。
【オプション①】/E
「/E」のオプションは、ディレクトリまたはサブディレクトリが空であってもコピーする、というオプションです。
【オプション②】/IF
「/XF」のオプションを付けて、そのあとスペース文字を1つ入れてファイルの拡張子を指定すると、robocopyコマンド実行時に、指定した拡張子のファイルだけがコピーされます。
拡張子の指定は、「txt」の場合は「*.txt」と記述します。
また、拡張子を複数指定したい場合は、「/IF」でファイルの拡張子のコピー対象設定を記述したその後ろに追記します。
追記する場合は、1つの拡張子に付き「/IF」を必ず記述してその後に拡張子を記述します。
下のように、1つの拡張子に対して「/IF」の記述を忘れないようにしましょう。
- 【誤】robocopy “%%~i” “%newFolder%\%%~ni” /E /IF *.txt *.csv
- 【正】robocopy “%%~i” “%newFolder%\%%~ni” /E /IF *.txt /IF *.csv
注目すべきコード⑧
次に見て頂きたいのは27行目です。
rem setlocalコマンドによって変更されたローカル環境変数の設定を元に戻す endlocal
コードの説明
以上のコードは、setlocalコマンドによって変更されたローカル環境変数の設定を元に戻す処理のコードです。
7行目で遅延環境変数展開を有効にしたのを、このコードで元に戻しています。
動作確認
「フォルダの例」をご覧ください。
最後に
この記事では、バッチファイルにドロップした複数のフォルダを新規フォルダへコピーする方法についてご説明しました。
なお今回のバッチファイルは、フォルダをコピーする際は指定した拡張子のファイルだけをコピーする指定をコードに盛り込んでいます。
バッチファイルにドロップするだけで新たにフォルダを作成し、そのフォルダの中にフォルダがコピーされますが、フォルダ配下にある一部の拡張子のファイルだけをコピーしたいという場合は本記事を参考にして頂けたら幸いです。
プログラミングのスキルを習得するなら
プログラミングのスキルを習得したい、今のスキルをもっと高めたい、そう考えているなら「プログラミングスクール」がおすすめです。
プログラミングのスキルの基礎を身につけるなら「TechAcademy」で1週間の無料体験があるので、これで「プログラミングの基礎」を学ぶのにおすすめですよ。