Windowsの右クリックメニューから複数ファイルをまとめて開く

提供:Turgenev's Wiki

複数のファイルを別々にではなく一度にまとめて開きたいということがある。すなわち”app.exe file1” “app.exe file2”…をそれぞれ実行するのではなく、”app.exe file1 file2 …”を実行したい。例えば複数の音楽ファイルを連続再生したいときなどである。

ただ、エクスプローラ上で複数ファイルを選択して開く(右クリックで「開く」を選ぶorエンターキー)と、別々に実行されてしまう。では、右クリックメニューからこれを実行するにはどうすればいいか?というのがこの記事のテーマである。

ついでに、パス長さ制限を超えるファイルやフォルダにおける機能制限も解決する。  

Windows10以前の右クリックメニューに戻す

まず、Windows11に移行すると右クリックメニューの項目数が大幅に削られており、とても使いにくいので、Windows10までの仕様に戻す必要がある。Windows 11 - 右クリックメニューを旧仕様に戻す方法 - PC設定のカルマなどに従って修正しよう。コマンド例は以下。これはユーザーごとの設定なので、管理者権限は不要である。

reg add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve

ファイルを開く操作ならダブルクリックでできるわけで、それでもあえてファイルを右クリックするユーザーの層を考えれば、使用頻度の高いメニューに絞る必要がないことは明らかである。右クリックメニューは動作が重いという問題点も指摘されてきたが、それなら項目数を削る以外の方法でパフォーマンスを改善するのが筋だろう。そもそも、Windows 11の右クリックメニューもそれほど快適な動作ではない。

なおバージョン22H2からはShift+右クリックで旧仕様のメニューが出るようになったようなので、それで十分という人は設定しなくてもよい。

ちなみにこれ以降も同じだが、HKEY_CURRENT_USER以下はユーザー別設定なのでPC自体の再起動をしなくてもログアウト(サインアウト)→ログイン(サインイン)で全て反映されるはず。また今回の例に関しては、実際にはexplorerの再起動で十分である。

動画の右クリックメニューの順番がおかしい

動画ファイル(mp4やmkvなど)に関して、右クリックメニューの順番がおかしくなるという問題がある。具体的には、全ファイル共通のメニュー(「お気に入りに追加」など)とClipchampのメニューが普通の「開く」よりも上に表示されてしまう。また単一ファイル選択時だと(関連付けがすでに設定されているにもかかわらず)「プログラムから開く」が太字になってしまっている。

  • 単一ファイル選択時
clipchamp-sing.png
  • 複数ファイル選択時
clipchamp-mult.png

これはどうやらClipchampのメニューが悪いらしく、Add or Remove Edit with Clipchamp Context Menu in Windows 11 Tutorial | Windows 11 ForumClipchamp context menu removal | Windows 11 Forumに書いてあった)やWindowsの右クリックの「Clipchampで編集」を削除する方法 | ナポリタン寿司のPC日記に書いてある通り、Clipchampのメニューを非表示にすると治る。コマンド例は以下。

reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked" /v {8AB635F8-9A67-4698-AB99-784AD929F3B4} /f
  • HKLMでも設定できる。また、「デバイス キャスト」を非表示にする場合はUUIDを{7AD84985-87B4-4a16-BE58-8B72A5B390F7}に変える。

Clipchampを表示したまま順番を治す方法は不明だが、自分でメニューを作ればできるかもしれない。Clipchampのメニューの実装に使われていると思われるIContextMenuについては後でも述べているのでそちらも参照。おそらくClipchampによるこのインターフェースの実装にバグがあるためにこのような挙動をしているのであろう。

以下に修正後の正しい表示を載せておく。いずれの例でも関連づけはデフォルトのメディア プレイヤーが使われているものと仮定している(書いていて気付いたが、同一アプリにもかかわらず「プレーヤー」「プレイヤー」の表記ゆれがある)。

  • 単一ファイル選択時
sing.png
  • 複数ファイル選択時
mult.png

不完全な解決策

本題に入る。まずは、不完全ではあるがそこそこ簡単な解決策を紹介する。それは右クリックメニューにある「送る」を使う方法である。エクスプローラのアドレスバーにshell:sendtoと入力すると「送る」メニューの元になっているフォルダを開くことができる。ここにショートカットやファイルを追加しておけば、それが右クリックメニューに表示され、選択されたファイルをまとめてコマンド引数として渡してくれる。ショートカットを編集すればオプションも渡せる(あるいはバッチファイルを突っ込んでもよい)。

  • 今後紹介する方法にも共通するが、ファイルの順番としては、メインとして選択されたもの(右クリックされたもの)から下方向に進んでいき、下端まで達したら一番上に戻ってそれから選択されたものの直前まで進む。例えばファイルが”0”から”9”までの10個あるフォルダで全選択をして”5”を右クリックして「送る」を使うと、5 6 7 8 9 0 1 2 3 4の順番で渡される。

しかしこの「送る」には弱点があり、[ref]で紹介したように、この「送る」メニューは260文字の長さ制限を超えるパスをもつファイルに対してはうまく機能しない。音楽ファイルなんかはアーティスト名も曲名も色々入って長大な名前になりがちで、実際に自分がこれで困ることになった。

もう一つ、「送る」メニューは拡張子に関連付けられないという問題がある。つまり、音声ファイルを一度に開くためだけのコマンドも、画像ファイルを一度に開くためだけのコマンドも、全てのファイルを対象とした「送る」メニューにまとめて入れざるを得ない。メニュー数が無駄に増えればそれだけ管理・操作もしづらくなる。ついでに言えば、「送る」を一旦クリックしてから中の項目を選ぶ手間もなかなかバカにできないところがある。

前提知識 - メニューを管理するレジストリ

右クリックメニュー関連の設定はレジストリを使って管理されている。この記事では上記「送る」の問題を解決する方法をこの後で2つ紹介するが、いずれもレジストリのcommandという名前のキー(設定内容に応じて色々な所に設置されている)を編集する必要がある。それにあたって、前提知識としてレジストリの内容をある程度理解しておく必要があるだろう。

この話題に関しては比較的多くのサイトで解説があるが、Windowsのバージョンごとにかなり頻繁に仕様が変わっているようで、不十分なサイトも多い。最も優れているのはWindowsレジストリ解剖記で、かなり量は多いが、バージョンによる挙動の違いまで細かく示されている。

この記事に必要な操作を行うためにはcommandの場所だけわかっていればいちおう十分だが、以下の内容くらいは覚えておいたほうがよい。

  • HKEY_CURRENT_USERはHKCUと略され、ユーザーごとの設定を管理する。原則、変更はユーザー権限のみで可能。色々いじっても比較的安全。
  • HKEY_LOCAL_MACHINEはHKLMと略され、システム全体(全ユーザー対象)の設定を管理する。変更には管理者権限が必要。設定は慎重に。
  • HKEY_CLASSES_ROOTはHKCRと略され、関連付け専用のもので、HKCU\Software\ClassesとHKLM\Software\Classesの内容を合わせたものが表示される。関連づけの設定を確認するにはここを見るのがいいが、設定を変更する際にはここをいじるとHKLMのほうが変わってしまうことがあるのでHKCU\Software\Classesを変更したほうがよい

以下では、設定方法を①ProgIDを使うもの②完全に独自のメニューを追加するもの と大きく二つに分けて記述する。

ProgIDを使うもの

このセクションに含まれる情報は比較的貴重なものである可能性があります。

特定の拡張子をもつファイルをダブルクリックやEnterで開くときに使われるプログラム、あるいは「既定のプログラム」あるいは「ファイルを開くプログラムの選択」のようなダイアログが表示されるときに表示されるプログラムは、このProgIDを用いて管理されている。この方法のメリットは、何より「ダブルクリックまたはEnterキー一発で起動できる」という操作性である。また、Windows11以前のメニューに戻さなくても使いやすい。

  • 複数選択した際は「送る」と同様の順番で渡されるが、右クリックをしない場合は”メインとして選択されたファイル”がどれであるかが若干分かりづらい。基本的には最後に(左)クリックされたものになるはずで、よく見るとそれだけ少し太い(濃い)枠で表示されていることがわかる。なので音楽再生時など複数ファイルを上のものから順にすべて渡したいときは、「先に一番下にあるファイルをクリックしてから、一番上にあるファイルをShift+ダブルクリック(あるいはShift+クリックしたあとEnter)する」というのが有効である。

一方で、設定のしくみはやや煩雑である。具体的には、拡張子.xxxに対して

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.xxx\UserChoice

というキーがあって、ここのProgIdの値をvalueとしたときのHKEY_CLASSES_ROOT\value\shell\open\commandの内容に従ってアプリケーションが起動される。

Windows10以降ではUserChoiceの中身を変更するためには普通の管理者権限やSYSTEMよりもさらに上位のTrustedInstaller権限が必要である。AdvancedRunなどを使ってTrustedInstaller権限で変更することは一応できたが、ハッシュ値の生成までちゃんとやっていないので自動で修正されてしまった(ここが解決できるかどうかは未調査)。従って、任意のコマンドを設定したい際は、まずUserChoiceの中身を変更するところだけエクスプローラーのダイアログを使い、その後でHKEY_CLASSES_ROOT\valueの中身を好きに変えるほうがよいだろう。

例えば新たなメニューを追加したい場合なら、以下のようにするとよい。

  • 今まで使われていない(乱数値など)名前をもつダミーのexeファイル(実行ファイルとして正しく機能する必要はなく、空のファイルでもいいし、拡張子がexeでなくてもよい)を用意する(ここではdummy.exeとする)
  • 関連付けたい拡張子のファイルの右クリックメニューから「プログラムを開く」を選択し、dummy.exeを選んで関連づける
    • これによりレジストリキーHKEY_CURRENT_USER\Software\Classes\Applications\dummy.exeが作られた上でUserChoiceProgIdにはApplications\dummy.exeが書き込まれる
  • HKEY_CURRENT_USER\Software\Classes\Applications\dummy.exe\shell\openの中身を自由に変更する。

完全に独自のメニューを実装する

これは、「PowerShellをここで開く」「VS Codeで開く」のように完全に独自の右クリックメニューを追加するものである。設定は意外と簡単である。また、フォルダに対する右クリックメニューや全ファイルに共通の右クリックメニューを追加するにはこの方法しかない。ただし、Windows10以前のメニューに戻さないと「その他のオプション」を押す手間がかかるので注意。

拡張子ごとの設定はHKEY_CLASSES_ROOT\SystemFileAssociationsにある(編集時はHKEY_CURRENT_USER\Software\Classes\SystemFileAssociationsを使うのがいいだろう)(比較的新しいWindowsだとHKEY_CURRENT_USER\Software\Classes\SystemFileAssociationsキー自体が存在しないことがあるが、自分で作ればちゃんと動作する)。commandキーはHKEY_CURRENT_USER\Software\Classes\SystemFileAssociations\.xxx\shell\yourcommandname\commandのような場所に作られることになる。

また、全てのファイルを対象にするメニューはHKEY_CLASSES_ROOT\SystemFileAssociations\*、フォルダを右クリックしたときのメニューはHKEY_CLASSES_ROOT\Directory、ドライブ(C:\など)を右クリックしたときのメニューはHKEY_CLASSES_ROOT\Drive、フォルダ(・ドライブ)の背景(何もないところ)を右クリックしたときのメニューはHKEY_CLASSES_ROOT\Directory\Background以下でそれぞれ管理されている。また、HKEY_CLASSES_ROOT\AllFilesystemObjectsというのもあり、これはディレクトリとファイルの両方に適用される(ドライブやフォルダ背景には影響なし)。

複数種類に一括で追加?

HKEY_CLASSES_ROOTにはPerceivedTypeという値があり、これにvideoなどと指定されている場合はHKEY_CLASSES_ROOT\SystemFileAssociations\videoにある設定が反映される(これによって複数種類のファイルに共通するメニューが作れる)…というような情報もあったのだが、手元のWindows 11では全く反映されなかった。

そもそもPerceivedTypeに複数種類が指定できるか不明だったりと色々と意義が怪しいので諦めて各拡張子ごとに追加するのがよいのではないかと思う。CLSIDの部分は共通化されているわけなのでそれほど非効率な二重管理ということにもならないだろう。(そもそもこの辺のWindowsの仕様はころころ変わるっぽいのであまり頑張ってもしょうがないかも?)

Directory\Backgroundの表示

エクスプローラーの左側のエリアにあるフォルダやドライブを右クリックしたときのメニューには、なぜかDirectory\Backgroundの内容も表示されてしまう。そのうえ、これらには正しくパラメータが渡されない(commandに直接書くときは%Vなどが入っていると起動せず、COM使用(少なくともDelegateExecute)で受け取る方法も不明)。

ただ、DirectoryやDriveに同名のメニューが登録されている場合はそちらが優先される。しかし、これを利用してメニューを非表示にすることはできない。(DirectoryやDriveのほうにLegacyDisableを書いたら、そもそもそちらが無かったのと同じになるっぽい)

実際には、Directory\Backgroundに設定するメニューはDirectoryにもDriveにも等しくあったほうがいい場合が多いと思うので、そのように設定するとよいだろう。

その他設定項目

本筋とは関係ないので詳細は省くが、その他にもこれらのキーでは様々な設定ができる。

  • Iconによるアイコンの設定
  • &によるキーの設定(「"編集(E)"のEみたいなやつ」)
  • MUIVerb(多分、言語設定ごとの表示文字列の切り替えとかができるようになるやつ)
  • AppliesToDefaultAppliesToによる表示条件の設定
  • HasLUAShieldによる「管理者アイコン」の表示(Iconとの併用可)
    • これも実は上と同様にAQS書式で管理者アイコンの表示条件を設定できる
    • このアイコン自体はSystem32のimageres.dllとかUserAccountControlSettings.exeとかに入っている
  • SubCommandsによるサブメニューの登録
    • 手元のWindows11で試した限り、DirectoryDriveではうまくいくがDirectory\Backgroundだとサブメニューが出ない?
  • ExtendedSubCommandsKey値による他のshellキーへの参照によるサブメニューの登録
  • ExtendedによってShift+右クリックしたときのみ表示させる
  • 設定例: Add or Remove 'Open in Windows Terminal as administrator' context menu | Tutorials

ContextMenuHandlers(IContextMenu)を用いた実装

このセクションに含まれる情報は比較的貴重なものである可能性があります。

先ほどのClipchampのメニュー項目などはここまで述べたようにレジストリ内に静的に設定されているものではなくCOM(Component Object Model)を用いて外部のDLLの関数から動的に追加されているものである(ただDLLの指定自体はレジストリ内のInProcServer32のようなキーにあるはず)。Clipchamp以外だと7-ZipやPDF XChange Editorなどのメニューはこれを用いて実装されている。レジストリのXXX\shellex\ContextMenuHandlersといったキー以下に設定されているものはこれに分類される。

詳しくはIContextMenuなどのキーワードで検索すると出てくるCustomizing a Shortcut Menu Using Dynamic Verbs - Win32 apps | Microsoft Learnなどを読むとよさそうだが、実装はかなり難解である。Clipchampもこの部分で不適切な実装をしたために順番がおかしくなったのではないかと思われる。

動作確認できたサンプルとしては、https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/Win7Samples/winui/shell/appshellintegration/NonDefaultDropMenuVerbはIContextMenuを使って実装されており、dllをビルドしてCLSIDのInProcServer32でそれを指定するとちゃんと右クリックメニューが追加される。

また、メニューを追加する関数であるQueryContextMenuが呼ばれる時点で、引数となっているファイルの情報がわかる(Initialize関数においてIDataObjectが渡されているのでそれをクラスのフィールドなどとして持っておけばよい)ので、特定の拡張子のファイルのみに対してメニューを表示することもできる。もちろんファイルの内容まで読み取ってからメニューを表示するといったこともできるが、そこまですると右クリックするだけで動作が重くなるといった副作用が大きくなるのでやめた方が無難だろう。ただ、スタートメニューへのピン留め{a2a9545d-a0c2-42b4-9708-a0b2badd77c8}やPDF XChange Editor(9.3や10.2.1で確認)のメニューは実際にそのような挙動をする(余談だが、InfoTipの表示もexplorerが操作しづらくなる原因なのでshowinfotipを0にしたほうがいい)(サムネイルなどはバックグラウンドで並列に走るので操作にはあまり影響がない)。またエラーが発生した場合はexplorer自体が強制終了することもあり、全体的に実装は慎重に行ったほうがよい。

コード例

拡張子が.tで始まるファイル(*.txt, *.ttfなど)のみにメニューを追加するサンプル(から抜粋)。

IFACEMETHODIMP CNonDefaultDropMenuVerb::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/)
{
    FORMATETC fmte = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    STGMEDIUM medium;
    HRESULT hr = _pdtobj->GetData(&fmte, &medium);
    if (SUCCEEDED(hr))
    {
        HDROP hdrop = (HDROP)medium.hGlobal;
        WCHAR szFile[MAX_PATH];
        DragQueryFile(hdrop, 0, szFile, ARRAYSIZE(szFile));
        const WCHAR* ext = wcsrchr(szFile, L'.');
        ReleaseStgMedium(&medium);
        if (ext && *(ext+1) != L't') {
            return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);  // Add nothing
        }
    }
    else
    {
        return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);  // Add nothing
    }

    WCHAR szMenuItem[80];

    LoadString(g_hinst, IDS_CHECKDROP, szMenuItem, ARRAYSIZE(szMenuItem));
    InsertMenu(hmenu, indexMenu++, MF_BYPOSITION, idCmdFirst + IDM_CHECKDROP, szMenuItem);

    LoadString(g_hinst, IDS_CHECKNETRESOURCES, szMenuItem, ARRAYSIZE(szMenuItem));
    InsertMenu(hmenu, indexMenu++, MF_BYPOSITION, idCmdFirst + IDM_CHECKNETRESOURCES, szMenuItem);

    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (USHORT)(2));  // indicate that we added 2 verbs.
}
  • 特定の拡張子に対して追加できるのは以下で知った
    • できるという情報

registry - How to add context menu to one specific File - Stack Overflow

    • 実際のコード

freeimagerip/Thumb.cc at master · nyfair/freeimagerip

IContextMenuの今後について

Windowsの右クリックメニューが重いと良く言われるのはこのような高い自由度をもつIContextMenuに起因するものであると思われる。Windows11ではIContextMenuよりIExplorerCommandがよいというのを見かけた(https://twitter.com/kenichiuda/status/1417266893581295651や、そこで引用されているhttps://twitter.com/madonomori/status/1417265763363168263)。https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/Win7Samples/winui/shell/appshellintegration/ExplorerCommandVerbも見てみる必要があるかも。

ただまあMicrosoftのことなのでIContextMenuもあと10年くらいは使えるだろう。

サブメニュー

IContextMenuは自由度が高いのでサブメニューなども実装できるはず(7-Zipなどもそうしていると思われる)。またこのような記事もあった: デスクトップのシェルメニューをサブメニューにする | Nonsubject

Windows11の右クリックメニューへの追加

これはどうやらますます面倒になりそうで、リリース済のWindowsストアアプリをインストールするか開発者モードを有効にしないと自分の好きなメニューを追加できない(多分)上、アプリ1つにつき1メニューしか追加できないらしい。

解決策①COMを利用する

このセクションに含まれる情報は比較的貴重なものである可能性があります。

まずは、COMを用いて実装するという方法がある。基本的にはこちらが綺麗な解決策である。

IExecuteCommandというインターフェースを具体的に実装しているMicrosoftのサンプルがあったので、それを参考に、「任意コマンドを引数にとり、取得したファイル・フォルダの情報をそのコマンドの標準入力にUTF-8で送信する」というプログラムを作成した。

link_preview

COMを使っていることからわかるように、コマンドラインを介さず直接Explorerからデータが送られてくるので、他の方法に共通してみられるパス長さやファイル個数の制限が(事実上)皆無であり、非常に強力である。

このセクションの内容は未完成であり、今後の加筆が予定されています。催促は管理者までお気軽にどうぞ。

使い方

詳しい使い方は上記レポジトリのREADMEも参照。

基本

引数となる(実際に起動したい)コマンドはレジストリキー

HKEY_CURRENT_USER\Software\Classes\CLSID\{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\LocalServer32の既定の値で設定する。

その上で該当メニューに対応するcommandキー(レジストリの各所にある)にDelegateExecuteという値を作成して{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}を書き込むことで起動できる(commandの既定値よりもDelegateExecuteが優先される)。

IDropTargetを用いた実装

IExecuteCommandではなくIDropTargetというインターフェースを用いてもほぼ同じことができそうであった。対応するサンプルはhttps://github.com/microsoft/Windows-classic-samples/tree/main/Samples/Win7Samples/winui/shell/appshellintegration/DropTargetVerbである。IExecuteCommandとの機能的な違いはあまりよくわからないが、https://learn.microsoft.com/en-us/windows/win32/shell/samples-droptargetverbを読む限り、DropTargetのほうが古くからあるようである。CLSIDの登録までは同じだが、commandのかわりにDropTargetキーを使用し、DelegateExecute値のかわりにCLSID値を使う(ソースを読めばわかる)。

解決策②プロセス間通信で頑張る

このセクションに含まれる情報は比較的貴重なものである可能性があります。

「プロセス間通信を使って頑張る」という方法もある。要するに、コマンドとしては別々に渡されたとしても、既に立ち上がっているプロセスがあるときはそちらに投げて終了するようにすれば、一つのプロセスでまとめて開けるというわけである。

この部分を代わりにやってくれるものとしてはhttps://github.com/zenden2k/context-menu-launcherがある。これを少し改善したフォークとしてhttps://github.com/KnIfER/SingleInstance-Launcherがあり、さらに自分が64bit版のビルドを加えたものがhttps://github.com/ge9/SingleInstance-Launcherにある。

ただ、これはCOMを使う方法とは違っていくつかの欠点がある。

  • ファイル個数の上限
    • ProgIDを使って開く場合には、選択個数がデフォルトで15個までに設定されており、これはMultipleInvokePromptMinimum値(詳しくは他サイト)の変更により増やせるが確実ではない(上限に諸説あり)。
    • 独自メニューの場合は、"MultiSelectModel"を"Player"にすることでファイル数上限が100個になるが、それより大きくはできない。
  • 長さ制限(260文字)を超えるパスをもつフォルダでは失敗する(詳しくはWindowsのパス長さ制限に関して を参照)。
  • プロセス間通信を使っているため、起動時にラグがあったりすると、ごく稀に渡されたファイルの順番が乱れることがある。

SingleInstance-Launcher - 基本的な使い方

上記GitHubリポジトリから実行ファイルをダウンロードしてどこか分かりやすい場所に置く。インストールなどは不要である。筆者がリリースした実行ファイルを信用できない・改変したいなどの場合はソースコードをどうぞ。言語はC++。ファイルの順番が乱れにくくなる改善など大歓迎。

README.mdにもあるが起動に用いる基本的な構文(レジストリに登録する値)は以下のようである(※ここでは64bit版を使うものとして説明しているが、32bit版でも全く同様)。

"C:\path\to\singleinstance_x64.exe" "%1" "C:\Program Files\path\to\app.exe" "$files" --si-timeout 1000 --option-to-app-1 --option-to-app-2

"C:\path\to\singleinstance_x64.exe"、"%1"、"C:\Program Files\path\to\app.exe"、"$files"の順番はおそらくこの通りである必要がある。その後にあるものはapp.exeにオプションとしてそのまま渡されるが、--si-timeout nに限り、singleinstance_x64.exeが解釈し、app.exeに渡されない。このオプションはSingleInstance-Launcherに対して次のファイルが渡されてくるのを待つタイムアウト期間をミリ秒で指定するものである。短すぎると、右クリックメニューの処理が遅い場合に途中で打ち切られてしまう可能性がある。長すぎると、その期間待つまでapp.exeは呼ばれないため、タイムラグが長く不便に感じる可能性がある。特に動作が重いPCでなければ1000(1秒)くらいにしておけば十分だろう。もう少し短くてもいいかもしれない。

%1や$filesの両側にダブルクォーテーションがないと、空白を含むファイル名を正しく扱えない。GitHubのサンプルでは付いていないものもあるので注意。