PowerShell+robocopyで拡張子別にファイルを一括移動する方法
概要
今回はPowerShellで拡張子別にファイルを一括移動する方法について紹介していきます。
というのもGoogle Takeoutから大量にデータをダウンロードすると、画像・動画・JSONがごちゃ混ぜで困りますよね(- -;
手作業で振り分けるのは現実的じゃないので、コマンドでサクッと分類したい所です。
ここではrobocopyを使って、.jpg/.png/.mp4などの拡張子だけを別フォルダへ移動する手順を紹介していきます!
robocopyで拡張子フィルタをかけて移動し、forfilesでフォルダ階層を平らに均し、最後に件数チェックで取りこぼしを確認する、という3ステップの流れです。
これで大量画像の整理が一瞬で終わります。
それではやっていきましょう!
注意して、自己責任で実行するようにしてください。
目次
robocopyとforfilesの役割分担
本題に入る前に、今回使う2つのコマンドの守備範囲をざっくり整理しておきます。
- robocopy(拡張子フィルタ+移動を担当)
*.jpgのようなワイルドカードで対象拡張子だけを抜き出し、サブフォルダごと別の場所へ移動/コピーできる。標準搭載で速いのが強み
- forfiles(フォルダ階層の平坦化を担当)
- robocopyが引き継いだフォルダ構成を崩し、全ファイルを1つのフォルダ直下にまとめ直すのに使う
robocopyは元のフォルダ構成をそのまま引き継いでコピーするので、最終的にフォルダ直下へ全部まとめたい場合はforfilesとの合わせ技になる、という点だけ先に頭に入れておいてください。
初期状態のフォルダ構成
今回の手順実行前のフォルダ構成は下記のようなイメージです。
手順を実行するにつれて、フォルダ内の状態がどう変化するのか各手順に書いているので、参考にしてみてください。
- folder1
- aaa.png
- bbb.json
- folder2
- ccc.mov
- ddd.mp4
- eee.json
手順
再帰的に特定の拡張子のファイルを移動
再帰的にファイルを移動するコマンドを実行します。
実行すると、特定の拡張子のファイルを任意のフォルダに移動することができます。
コマンド
1 | robocopy "[移動元パス]" "[移動先パス] " [拡張子1] [拡張子2 ...] /S /MOV /NFL /NDL |
例:画像&動画のコピー
1 | robocopy ".\google_export\" ".\google_export_photo_only\" *.jpg *.jpeg *.png *.heic *.mp4 *mov *.MOV /S /NFL /NDL |
例:画像&動画の移動(個人的には非推奨)
1 | robocopy ".\google_export\" ".\google_export_photo_only\" *.jpg *.jpeg *.png *.heic *.mp4 *mov *.MOV /S /MOV /NFL /NDL |
- /S
- 再帰的にサブフォルダを探索(空フォルダは無視)
- /MOV
- ファイルを移動(コピー後、元ファイルを削除)
- ※このオプションを無くすと、コピーとなる
- /NFL
- 実行中にファイル一覧のログを表示しない
- ※ このオプションを無くすと、 ログを表示される
- /NDL
- 実行中にディレクトリ一覧のログを表示しない
- ※ このオプションを無くすと、 ログを表示される
移動先パスに画像と動画が配置されることを確認できると思います。
しかしこの方法の場合フォルダ構成も引き継ぐので、
次の手順でフォルダ構成を削除していきます。
- folder1
- aaa.png
- folder2
- ccc.mov
- ddd.mp4
ちなみに最初は/MOVを外したコピー版でテスト実行するのがお勧めです(^^b
元ファイルが手元に残っている状態で結果を確認できるので、万が一拡張子の指定をミスしても安全ですよね。
コピーで結果に納得できてから、改めて/MOV付きの移動版を流す、という二段構えにすると事故りにくいです。
フォルダ階層を平坦化してファイルを1つのフォルダにまとめる
robocopyコマンドだとフォルダ構成もコピーされる為、
フォルダ構成を無くし、フォルダ直下にすべてのファイルが配置されるようにします。
念のため新たに作成したフォルダにコピーする形とします。
コマンド
1 | forfiles /P "[移動元パス] " /S /M * /C 'cmd /c copy @path "[移動先フルパス]"' |
例:画像&動画のコピー
1 | forfiles /P ".\google_export_photo_only\" /S /M * /C 'cmd /c copy @path "C:\Users\user1\google_export_photo_only_comp\"' |
- /P
- 検索フォルダを指定
- /S
- サブフォルダをすべて含めて再帰検索
- /M
- 移動対象ファイル名を指定
- ※今回は*なので全部のファイルが対象
- /C
- コマンドを実行
- ※今回はファイルをコピーするコマンドを実行
- @path
- 探査で発見されたファイルパス
- aaa.png
- ccc.mov
- ddd.mp4
このようにfolder1やfolder2といった階層が消えて、すべてのファイルが移動先フォルダの直下に並びます。
平坦化する前に、同名ファイルが無いかだけ気にしておくと安心です。
ファイルが移動できたか確認
すべてのファイルが正常に移動できたか確認するために、移動元のファイル数と移動先のファイル数が一致していることを確認します
コマンド
1 | (Get-ChildItem "[移動元パス or 移動先パス ].\google_export\" -Recurse -Include [拡張子1] [拡張子2 ...] -File).Count |
例:画像&動画の場合
1 |
|
Get-ChildItemの-Includeにはカンマ区切りで複数の拡張子をまとめて渡せるので、画像と動画をひとまとめに数えられます。-Fileを付けるとフォルダを除いてファイルだけをカウントしてくれるので、件数がブレにくいです。-Recurseや-Filterの基本的な使い方は
get-childitemの-Recurse / -Filterの基本🔗 shinpinoshi.comでまとめているので、合わせて確認してみてください。
ここで件数に差異がある場合、重複ファイルが存在する可能性が高いため、確認する。
よくあるつまずきポイント
最後に、自分が実際にハマった所をいくつか共有しておきます。
- robocopyの終了コードは0以外でも正常なことがある
- robocopyはファイルをコピーすると終了コード1を返す仕様で、これはエラーではありません。8以上で本当の失敗、と覚えておくと慌てずに済みます
- ワイルドカードの大文字小文字に注意
*.MOVと*movのように、想定する表記ゆれを拡張子リストに足しておくと取りこぼしが減ります
- 移動先フォルダは事前に作っておく
- パスのタイプミスで意図しない場所に散らばると後始末が大変なので、まず空フォルダを用意してから流すのが安全です
迷ったらまずコピーで挙動を確かめ、件数チェックで一致を見てから移動に切り替える。
この流れさえ守れば、大量ファイルでも安全に振り分けられます。
締め
これでファイルの移動ができたと思います。
コマンド一つ一つは難しいですが、手動でやるより圧倒的に楽に早くできると思います。
こんな感じの便利なコマンドを自分のサイトでは色々紹介しています。
良ければ他の記事も見ていってください!
以上となります。
大事なファイルを安全にお引越ししましょう!
それではお疲れさまでした!





