【bat】バッチファイルで特定のフォルダを検索して移動する完全ガイド|for /d・dir /s・再帰検索・部分一致・複数条件・ドライラン・実践パターンまで徹底解説

【bat】バッチファイルで特定のフォルダを検索して移動する完全ガイド|for /d・dir /s・再帰検索・部分一致・複数条件・ドライラン・実践パターンまで徹底解説 bat

バッチファイルで「特定の名前やパターンに一致するフォルダを検索し、そのフォルダを別の場所に移動する」処理は、ファイル整理・アーカイブ・ビルド後処理などで頻繁に使われます。例えば「_done で終わるすべてのフォルダを archive フォルダに移動する」「深い階層に埋まっている output フォルダを一か所に集める」といった作業を自動化できます。Windowsバッチでは for /d(直下検索)と dir /s /ad(再帰検索)の2つのアプローチがあり、用途に応じて使い分けます。本記事では検索パターンの指定から、複数条件・再帰・ドライランまで完全解説します。

この記事でわかること

  • for /d でディレクトリ直下のフォルダを検索・移動する基本パターン
  • 完全一致・部分一致・前方一致・後方一致の各検索方法
  • dir /s /ad /b + for /f でサブフォルダを再帰検索する方法
  • 複数キーワード(OR / AND)での検索条件の組み合わせ方
  • 検索で見つかったフォルダを別の場所にまとめて移動する方法
  • 移動先に同名フォルダがある場合の安全な処理パターン
  • ドライラン(実際には移動せず検索結果だけ確認する)の実装方法
  • 実践例3本(完了プロジェクト整理・ビルド出力収集・古いキャッシュ移動)
スポンサーリンク

1. 基本:for /d で直下フォルダを検索・移動する

for /d は指定ディレクトリ直下のサブフォルダを列挙するコマンドです。ワイルドカード(*?)でフォルダ名のパターンを指定し、一致したフォルダを move コマンドで別の場所に移動します。

:: 基本構文
:: for /d %%F in ("検索パス\パターン") do (
::     一致したフォルダに対する処理
:: )

@echo off
setlocal

set SEARCH_DIR=C:\work
set DEST_DIR=C:\archive

if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"

:: SEARCH_DIR 直下のすべてのフォルダを移動
for /d %%F in ("%SEARCH_DIR%\*") do (
    move "%%~fF" "%DEST_DIR%\" >nul 2>&1
    if %ERRORLEVEL% equ 0 (
        echo [OK] %%~nxF → %DEST_DIR%
    ) else (
        echo [FAIL] %%~nxF
    )
)

1-1. 検索パターン別のワイルドカード指定

検索条件 パターン例 一致するフォルダ名の例
すべてのフォルダ * project_01, backup_2024, temp など任意
前方一致(プレフィックス) project_* project_01, project_alpha など
後方一致(サフィックス) *_done task_done, build_done など
部分一致(含む) *backup* my_backup_2024, backup_old など
1文字ワイルドカード task_?? task_01, task_AB など2文字の任意
完全一致 output(ワイルドカードなし) output という名前のフォルダのみ
@echo off
setlocal

set SEARCH_DIR=C:\work
set DEST_DIR=C:\archive

if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"

:: 前方一致: "project_" で始まるフォルダを移動
for /d %%F in ("%SEARCH_DIR%\project_*") do (
    echo [FIND] %%~nxF
    move "%%~fF" "%DEST_DIR%\" >nul 2>&1
    if %ERRORLEVEL% equ 0 ( echo  → 移動完了 ) else ( echo  → 移動失敗 )
)

:: 後方一致: "_done" で終わるフォルダを移動
for /d %%F in ("%SEARCH_DIR%\*_done") do (
    echo [FIND] %%~nxF
    move "%%~fF" "%DEST_DIR%\" >nul 2>&1
    if %ERRORLEVEL% equ 0 ( echo  → 移動完了 ) else ( echo  → 移動失敗 )
)
for /d のワイルドカード検索はカレントディレクトリ直下のみ
for /d %%F in ("C:\work\*") doC:\work直下にあるフォルダのみを対象とします。サブフォルダの中にある同名フォルダは対象になりません。サブフォルダを再帰的に検索するには、セクション3で紹介するdir /s /ad /b を使った方法を使ってください。

2. 完全一致・部分一致で検索する

2-1. 完全一致で特定名のフォルダを探す

ワイルドカードなしで特定のフォルダ名だけを完全一致で検索するには、for /d のパターンにそのまま名前を指定します。ただし if exist を使った方がより直接的です。

@echo off
setlocal

set SEARCH_DIR=C:\work
set FOLDER_NAME=output
set DEST_DIR=C:\archive

:: 方法1: if exist でフォルダの存在を直接チェック
if exist "%SEARCH_DIR%\%FOLDER_NAME%\" (
    echo [FIND] %FOLDER_NAME% が見つかりました
    if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"
    move "%SEARCH_DIR%\%FOLDER_NAME%" "%DEST_DIR%\" >nul 2>&1
    if %ERRORLEVEL% equ 0 (
        echo [OK] 移動完了: %FOLDER_NAME% → %DEST_DIR%
    ) else (
        echo [ERROR] 移動失敗
        exit /b 1
    )
) else (
    echo [INFO] %FOLDER_NAME% が見つかりませんでした
)

:: 方法2: for /d の完全一致パターン
for /d %%F in ("%SEARCH_DIR%\output") do (
    echo [FIND] %%~nxF
    move "%%~fF" "%DEST_DIR%\" >nul 2>&1
)

2-2. 部分一致(名前にキーワードが含まれる)で探す

ワイルドカードだけでは難しい「名前の途中にキーワードが含まれるフォルダ」の検索には、for /d ですべてのフォルダを列挙した後にecho %%~nxF | findstr /i でキーワード検索する方法が使えます。

@echo off
setlocal enabledelayedexpansion

set SEARCH_DIR=C:\work
set KEYWORD=backup
set DEST_DIR=C:\archive

if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"

set COUNT=0

:: すべてのフォルダを列挙し、名前に KEYWORD が含まれるものを移動
for /d %%F in ("%SEARCH_DIR%\*") do (
    :: フォルダ名に KEYWORD が含まれるか findstr でチェック
    echo %%~nxF | findstr /i "%KEYWORD%" >nul 2>&1
    if not errorlevel 1 (
        echo [FIND] %%~nxF
        :: 移動先に同名フォルダがないかチェック
        if exist "%DEST_DIR%\%%~nxF\" (
            echo [SKIP] 移動先に同名フォルダが存在: %%~nxF
        ) else (
            move "%%~fF" "%DEST_DIR%\" >nul 2>&1
            if !ERRORLEVEL! equ 0 (
                echo  → 移動完了
                set /a COUNT+=1
            ) else (
                echo  → 移動失敗
            )
        )
    )
)

echo.
echo !COUNT! 件のフォルダを移動しました

3. dir /s /ad で深い階層まで再帰的に検索する

for /d はディレクトリ直下しか検索しませんが、dir /s /ad /b を使うと指定フォルダ以下のすべての階層を再帰検索できます。for /f でその出力を受け取り、移動処理を行います。

:: dir オプション:
:: /s : サブフォルダを再帰的に検索
:: /ad: ディレクトリ(フォルダ)のみを対象
:: /b : 名前のみを出力(フルパス出力には /s /b を組み合わせる)

@echo off
setlocal enabledelayedexpansion

set SEARCH_DIR=C:\work
set FOLDER_NAME=output
set DEST_DIR=C:\archive

if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"

set COUNT=0

:: dir /s /ad /b で再帰的にフォルダを検索(フルパスで出力される)
for /f "delims=" %%F in ('dir /s /ad /b "%SEARCH_DIR%\%FOLDER_NAME%" 2^>nul') do (
    echo [FIND] %%F

    :: 移動先に同名フォルダがないかチェック
    if exist "%DEST_DIR%\%%~nxF\" (
        echo [SKIP] 移動先に同名フォルダが存在: %%~nxF
    ) else (
        move "%%F" "%DEST_DIR%\" >nul 2>&1
        if !ERRORLEVEL! equ 0 (
            echo  → 移動完了
            set /a COUNT+=1
        ) else (
            echo  → 移動失敗(別プロセスが使用中の可能性)
        )
    )
)

if !COUNT!==0 (
    echo [INFO] %FOLDER_NAME% フォルダは見つかりませんでした
) else (
    echo.
    echo !COUNT! 件移動しました
)
dir /s /b はフルパスを出力するため %%F で直接 move に渡せる
dir /s /ad /bC:\work\subdir\output のようにフルパスを1行ずつ出力します。for /f "delims=" %%F で受け取ると%%F にフルパスが入り、%%~nxF でフォルダ名のみを取得できます。2^>nul は dir が「見つからない」と返すエラー出力を抑制します。

3-1. パターン指定で再帰検索する(部分一致 + 再帰)

@echo off
setlocal enabledelayedexpansion

set SEARCH_DIR=C:\work
set KEYWORD=cache
set DEST_DIR=C:\archive

if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"

set COUNT=0

:: dir /s /ad /b で全フォルダを再帰列挙し、findstr でキーワードフィルタ
for /f "delims=" %%F in ('dir /s /ad /b "%SEARCH_DIR%" 2^>nul ^| findstr /i "%KEYWORD%"') do (
    echo [FIND] %%F
    if exist "%DEST_DIR%\%%~nxF\" (
        echo [SKIP] 移動先に同名フォルダが存在: %%~nxF
    ) else (
        move "%%F" "%DEST_DIR%\" >nul 2>&1
        if !ERRORLEVEL! equ 0 (
            echo  → 移動完了
            set /a COUNT+=1
        ) else (
            echo  → 移動失敗
        )
    )
)

echo.
echo !COUNT! 件移動しました

4. 複数条件で検索する(OR / AND)

4-1. OR 条件:いずれかのキーワードに一致するフォルダを移動

@echo off
setlocal enabledelayedexpansion

set SEARCH_DIR=C:\work
set DEST_DIR=C:\archive

if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"

set COUNT=0

:: OR 条件: "done" または "complete" または "finished" を含むフォルダを移動
for /d %%F in ("%SEARCH_DIR%\*") do (
    echo %%~nxF | findstr /i "done complete finished" >nul 2>&1
    if not errorlevel 1 (
        echo [FIND] %%~nxF
        if exist "%DEST_DIR%\%%~nxF\" (
            echo [SKIP] 同名フォルダが移動先に存在
        ) else (
            move "%%~fF" "%DEST_DIR%\" >nul 2>&1
            if !ERRORLEVEL! equ 0 (
                echo  → 移動完了
                set /a COUNT+=1
            ) else (
                echo  → 移動失敗
            )
        )
    )
)

echo !COUNT! 件移動しました

4-2. AND 条件:すべてのキーワードを含むフォルダのみ移動

@echo off
setlocal enabledelayedexpansion

set SEARCH_DIR=C:\work
set DEST_DIR=C:\archive

if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"

set COUNT=0

:: AND 条件: "project" かつ "2024" を両方含むフォルダのみ移動
for /d %%F in ("%SEARCH_DIR%\*") do (
    set MATCH=0
    echo %%~nxF | findstr /i "project" >nul 2>&1
    if not errorlevel 1 (
        echo %%~nxF | findstr /i "2024" >nul 2>&1
        if not errorlevel 1 set MATCH=1
    )
    if !MATCH!==1 (
        echo [FIND] %%~nxF
        if exist "%DEST_DIR%\%%~nxF\" (
            echo [SKIP] 同名フォルダが移動先に存在
        ) else (
            move "%%~fF" "%DEST_DIR%\" >nul 2>&1
            if !ERRORLEVEL! equ 0 (
                echo  → 移動完了
                set /a COUNT+=1
            ) else (
                echo  → 移動失敗
            )
        )
    )
)

echo !COUNT! 件移動しました

5. 移動先に同名フォルダがある場合の対策

フォルダを移動する際、移動先に同名のフォルダが既に存在すると、move コマンドは同名フォルダの内側に移動してしまう(意図しないネスト)か、エラーになります。安全な処理のために事前チェックと代替対応が必要です。

@echo off
setlocal enabledelayedexpansion

set SEARCH_DIR=C:\work
set DEST_DIR=C:\archive

:: 今日の日付を YYYYMMDD 形式で取得(同名衝突時のサフィックス用)
for /f "tokens=2 delims==." %%D in ('wmic os get LocalDateTime /value ^| findstr LocalDateTime') do set DT=%%D
set TODAY=%DT:~0,8%

if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"

for /d %%F in ("%SEARCH_DIR%\project_*") do (
    set FNAME=%%~nxF

    if exist "%DEST_DIR%\!FNAME!\" (
        :: 同名フォルダが存在 → 日付サフィックスを付けて移動
        set NEW_NAME=!FNAME!_%TODAY%
        if exist "%DEST_DIR%\!NEW_NAME!\" (
            echo [SKIP] 日付付きでも同名フォルダが存在: !NEW_NAME!
        ) else (
            move "%%~fF" "%DEST_DIR%\!NEW_NAME!" >nul 2>&1
            if !ERRORLEVEL! equ 0 (
                echo [OK] !FNAME! → %DEST_DIR%\!NEW_NAME! ^(日付サフィックス付き^)
            ) else (
                echo [FAIL] !FNAME!
            )
        )
    ) else (
        move "%%~fF" "%DEST_DIR%\" >nul 2>&1
        if !ERRORLEVEL! equ 0 (
            echo [OK] !FNAME! → %DEST_DIR%
        ) else (
            echo [FAIL] !FNAME!
        )
    )
)
move の挙動:移動先の存在状態によって動作が変わる
move "C:\src\A" "C:\dst\A"C:\dst\A存在しない場合は正常に移動(名前そのまま)、存在する場合は C:\dst\A\A のように内側に移動してしまいます。フォルダ移動の詳細は バッチファイルでフォルダを移動する完全ガイド を参照してください。

6. ドライラン:移動せずに検索結果だけ確認する

大量のフォルダを移動する前に「何が検索にヒットするか」を確認したいことがあります。/dry フラグで移動処理をスキップし、検索にヒットしたフォルダ一覧だけを表示します。

@echo off
setlocal enabledelayedexpansion

:: /dry 引数でドライランモード(実際には移動しない)
set DRY=0
if /i "%~1"=="/dry" set DRY=1

set SEARCH_DIR=C:\work
set KEYWORD=done
set DEST_DIR=C:\archive

if !DRY!==1 (
    echo ===== ドライランモード(実際には移動しません) =====
) else (
    echo ===== 検索・移動モード =====
    if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"
)

set COUNT=0

for /d %%F in ("%SEARCH_DIR%\*") do (
    echo %%~nxF | findstr /i "%KEYWORD%" >nul 2>&1
    if not errorlevel 1 (
        if !DRY!==1 (
            echo [DRY] 移動予定: %%~nxF → %DEST_DIR%
        ) else (
            if exist "%DEST_DIR%\%%~nxF\" (
                echo [SKIP] 同名フォルダが存在: %%~nxF
            ) else (
                move "%%~fF" "%DEST_DIR%\" >nul 2>&1
                if !ERRORLEVEL! equ 0 (
                    echo [OK] %%~nxF → %DEST_DIR%
                ) else (
                    echo [FAIL] %%~nxF
                )
            )
        )
        set /a COUNT+=1
    )
)

echo.
echo 対象: !COUNT! フォルダ
if !DRY!==1 echo ^(ドライランのため実際には移動していません。/dry なしで再実行してください^)

:: 実行例:
::   確認のみ: batch.bat /dry
::   実際に移動: batch.bat

7. 再帰検索+ドライラン統合スクリプト

セクション3(再帰検索)とセクション6(ドライラン)を組み合わせた実用的な統合スクリプトです。深い階層に埋まったフォルダを検索して移動する場面で使えます。引数でキーワード・検索フォルダ・移動先を指定できます。

@echo off
setlocal enabledelayedexpansion

:: 使い方:
::   batch.bat /dry   ← ドライラン(検索結果を確認するだけ)
::   batch.bat        ← 実際に移動

set DRY=0
if /i "%~1"=="/dry" set DRY=1

set SEARCH_DIR=C:\work
set KEYWORD=output
set DEST_DIR=C:\archive\outputs

if !DRY!==1 (
    echo ===== ドライランモード =====
) else (
    echo ===== 検索・移動開始 =====
    if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"
)

set COUNT=0
set SKIP=0
set FAIL=0

:: dir /s /ad /b で再帰検索 + findstr でキーワードフィルタ
for /f "delims=" %%F in ('dir /s /ad /b "%SEARCH_DIR%" 2^>nul ^| findstr /i "%KEYWORD%"') do (
    set FNAME=%%~nxF
    set FPATH=%%F

    if !DRY!==1 (
        echo [DRY] !FPATH!
        set /a COUNT+=1
    ) else (
        if exist "%DEST_DIR%\!FNAME!\" (
            echo [SKIP] 移動先に同名フォルダが存在: !FNAME!
            set /a SKIP+=1
        ) else (
            move "!FPATH!" "%DEST_DIR%\" >nul 2>&1
            if !ERRORLEVEL! equ 0 (
                echo [OK] !FNAME! → %DEST_DIR%
                set /a COUNT+=1
            ) else (
                echo [FAIL] !FPATH!
                set /a FAIL+=1
            )
        )
    )
)

echo.
if !DRY!==1 (
    echo 検索ヒット: !COUNT! フォルダ
    echo ^(/dry なしで再実行すると実際に移動されます^)
) else (
    echo 移動: !COUNT! 件 / スキップ: !SKIP! 件 / 失敗: !FAIL! 件
)

8. よくあるエラーと対策

エラー / 症状 原因 対策
フォルダが見つからない(ヒット件数が0) ワイルドカードパターンが正しくない、または大文字/小文字が一致しない まず dir /b "%SEARCH_DIR%\*" で存在するフォルダ名を確認。findstr には /i を付ける
移動したら意図しない場所(ネスト)に入った 移動先に同名フォルダが既に存在し、その内側に移動された セクション5の事前チェックパターンで if exist "%DEST_DIR%\%%~nxF\" を追加
アクセスが拒否されました フォルダが別プロセスで使用中、または権限不足 フォルダを開いているアプリを終了させる。管理者権限でバッチを実行する
dir /s の検索が遅い 検索対象ディレクトリの配下にファイル・フォルダが大量にある 検索パスをより具体的にする(深いパスから開始)。検索パターンを拡張子やプレフィックスで絞り込む
for /f ループ内で変数が更新されない enabledelayedexpansion なしで %VAR% を使っている setlocal enabledelayedexpansion を宣言し、ループ内は !VAR! を使う
サブフォルダ内のフォルダが見つからない for /d はカレントディレクトリ直下しか処理しない dir /s /ad /b + for /f で再帰検索する(セクション3)

9. 実践例3本

実践例1:完了済みプロジェクトフォルダを一括でアーカイブに移動する

プロジェクトフォルダの命名規則として「完了したものには _done サフィックスを付ける」ルールがある場合、*_done パターンで検索してアーカイブに移動するパターンです。ドライランで確認後、本番実行します。

@echo off
setlocal enabledelayedexpansion

set DRY=0
if /i "%~1"=="/dry" set DRY=1

set PROJ_DIR=C:\projects
set ARCH_DIR=C:\archive

:: 今日の年月でアーカイブサブフォルダを作成
for /f "tokens=2 delims==." %%D in ('wmic os get LocalDateTime /value ^| findstr LocalDateTime') do set DT=%%D
set YYYYMM=%DT:~0,6%
set DEST=%ARCH_DIR%\%YYYYMM%

if !DRY!==1 (
    echo ===== ドライランモード =====
) else (
    if not exist "%DEST%\" mkdir "%DEST%"
    echo ===== アーカイブ開始 [移動先: %DEST%] =====
)

set COUNT=0

:: "_done" で終わるフォルダを検索
for /d %%F in ("%PROJ_DIR%\*_done") do (
    set FNAME=%%~nxF
    if !DRY!==1 (
        echo [DRY] !FNAME! → %DEST%
        set /a COUNT+=1
    ) else (
        if exist "%DEST%\!FNAME!\" (
            echo [SKIP] 同名が存在: !FNAME!
        ) else (
            move "%%~fF" "%DEST%\" >nul 2>&1
            if !ERRORLEVEL! equ 0 (
                echo [OK] !FNAME!
                set /a COUNT+=1
            ) else (
                echo [FAIL] !FNAME!
            )
        )
    )
)

echo.
if !DRY!==1 (
    echo 対象: !COUNT! フォルダ ^(確認後 /dry なしで実行^)
) else (
    echo 移動完了: !COUNT! フォルダ → %DEST%
)

実践例2:深い階層の output フォルダをすべて一か所に集める

複数のサブプロジェクトが生成した output フォルダを再帰検索で見つけて1か所のフォルダに集める実践パターンです。同名フォルダの衝突を防ぐため、親フォルダ名をプレフィックスとして付けながら移動します。

@echo off
setlocal enabledelayedexpansion

set DRY=0
if /i "%~1"=="/dry" set DRY=1

set SEARCH_DIR=C:\projects
set DEST_DIR=C:\collected_outputs

if !DRY!==0 (
    if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"
)

set COUNT=0

:: dir /s /ad /b で "output" という名前のフォルダを再帰検索
for /f "delims=" %%F in ('dir /s /ad /b "%SEARCH_DIR%\output" 2^>nul') do (
    :: 親フォルダ名を取得してプレフィックスとして使用(衝突防止)
    for %%P in ("%%~dpF.") do set PARENT=%%~nxP
    set NEW_NAME=!PARENT!_output

    if !DRY!==1 (
        echo [DRY] %%F → %DEST_DIR%\!NEW_NAME!
        set /a COUNT+=1
    ) else (
        if exist "%DEST_DIR%\!NEW_NAME!\" (
            echo [SKIP] 既に存在: !NEW_NAME!
        ) else (
            move "%%F" "%DEST_DIR%\!NEW_NAME!" >nul 2>&1
            if !ERRORLEVEL! equ 0 (
                echo [OK] %%F → %DEST_DIR%\!NEW_NAME!
                set /a COUNT+=1
            ) else (
                echo [FAIL] %%F
            )
        )
    )
)

echo.
if !DRY!==1 ( echo 検索ヒット: !COUNT! フォルダ ) else ( echo 収集完了: !COUNT! フォルダ )

実践例3:キーワードと日付条件を組み合わせた古いフォルダの移動

tmp を含む名前のフォルダのうち、for /f で取得した更新日が30日以上前のものだけを移動する」という日付条件付きの実践パターンです。フォルダの更新日時は for %%F ... %%~tF で取得できます。

@echo off
setlocal enabledelayedexpansion

set DRY=0
if /i "%~1"=="/dry" set DRY=1

set SEARCH_DIR=C:\work
set KEYWORD=tmp
set DEST_DIR=C:\old_tmp
set DAYS=30

if !DRY!==0 if not exist "%DEST_DIR%\" mkdir "%DEST_DIR%"

set COUNT=0

:: forfiles で DAYS 日以上前のフォルダを検索しキーワードフィルタ
for /f "delims=" %%F in ('forfiles /p "%SEARCH_DIR%" /d -%DAYS% /c "cmd /c if @isdir==TRUE echo @path" 2^>nul ^| findstr /i "%KEYWORD%"') do (
    :: forfiles の出力に含まれるクォートを除去
    set FPATH=%%~F
    set FPATH=!FPATH:"=!
    set FNAME=!FPATH!
    for %%G in ("!FPATH!") do set FNAME=%%~nxG

    if !DRY!==1 (
        echo [DRY] !FPATH! ^(%DAYS%日以上前^)
        set /a COUNT+=1
    ) else (
        if exist "%DEST_DIR%\!FNAME!\" (
            echo [SKIP] 同名が存在: !FNAME!
        ) else (
            move "!FPATH!" "%DEST_DIR%\" >nul 2>&1
            if !ERRORLEVEL! equ 0 (
                echo [OK] !FNAME!
                set /a COUNT+=1
            ) else (
                echo [FAIL] !FPATH!
            )
        )
    )
)

echo.
echo 対象: !COUNT! フォルダ
if !DRY!==1 echo ^(/dry なしで再実行^)

フォルダの一覧取得については バッチファイルで指定フォルダ配下のフォルダ一覧を取得する方法完全ガイド、フォルダのコピーについては バッチファイルでフォルダをコピーする方法完全ガイド も参照してください。

10. まとめ:フォルダ検索・移動チートシート

やりたいこと コマンド / パターン
直下フォルダを前方一致で検索 for /d %%F in ("dir\prefix_*") do ...
直下フォルダを後方一致で検索 for /d %%F in ("dir\*_suffix") do ...
直下フォルダを部分一致(キーワード)で検索 for /d + echo %%~nxF | findstr /i "kw"
完全一致で特定フォルダを移動 if exist "dir\name\" then move ...
サブフォルダを再帰検索 dir /s /ad /b "dir" | findstr /i "kw"for /f で受取
OR 条件(複数キーワードのいずれかを含む) findstr /i "kw1 kw2 kw3"(スペース区切り)
AND 条件(複数キーワードをすべて含む) findstr を2回適用し MATCH フラグで制御
移動先の同名フォルダ衝突を防ぐ if exist "%DEST%\%%~nxF\" で事前チェック、衝突時は日付サフィックスを付与
ドライラン(確認のみ) if /i "%~1"=="/dry"move をスキップ

FAQ

Qfor /d でサブフォルダ内のフォルダが検索されません。

Afor /d %%F in ("dir\*") は指定ディレクトリの直下のフォルダのみを対象とします。サブフォルダを含めて再帰検索するには、セクション3で紹介したdir /s /ad /b "dir" 2>nul の出力を for /f "delims=" %%F in ('...') do で処理してください。

Qfindstr /i でキーワード検索しているのに一致しないフォルダがあります。

A主な原因として①findstr がデフォルトで正規表現を使うため、ドット(.)やアスタリスク(*)が特殊文字として解釈されている、②フォルダ名に全角文字が含まれていてマッチしない、の2点が考えられます。リテラル検索には findstr /l /i を、スペースを含むキーワードには findstr /c:"kw" を使ってください。

Qdir /s で検索すると同名のフォルダが複数見つかります。どうしたらよいですか?

Adir /s /ad /b "dir\output" は複数のサブフォルダに output がある場合すべてを列挙します。一括で移動すると移動先で名前衝突が起きます。セクション9の実践例2のように親フォルダ名をプレフィックスに付けた名前で移動するか、1件ずつ手動で確認しながら処理するドライランパターンを使ってください。

Q検索条件に一致するフォルダが0件でも終了コードがエラーになります。

Adir /s /ad /b "dir\name" 2>nul2>nul はエラーメッセージ(見つからない旨の出力)を抑制しますが、dir 自体はファイルが見つからない場合に終了コード1を返します。for /f がループを1回も実行しない場合はエラーにはなりませんが、スクリプトの後続処理で %ERRORLEVEL% を参照している場合は注意してください。

Qmove コマンドで「アクセスが拒否されました」が出ます。

A主な原因は①フォルダ内のファイルが別プロセス(エクスプローラー・エディタ等)で開かれている、②権限不足(管理者権限が必要なパスへのアクセス)の2つです。①はファイルを閉じてから再実行、②はバッチを右クリック→「管理者として実行」してください。フォルダ移動の詳細は バッチファイルでフォルダを移動する完全ガイド を参照してください。

Qfor /d のワイルドカードで大文字/小文字は区別されますか?

AWindows のファイルシステム(NTFS)は大文字/小文字を区別しないため、for /d %%F in ("dir\Project_*")project_01PROJECT_alpha のどちらにもマッチします。ただし findstr でのキーワードフィルタ時に意図しないマッチが起きた場合は/i の有無で制御できます。