60801


**やりたいこと**  
「C:\xディレクトリ」内の「任意の階層」にある「HOGEディレクトリ名」内にある全ファイルを抽出したい

* * *

**最初に試したこと**  
currentディレクトリから

[code]

    C:\x>for /r /d %a in (*HOGE) do echo "%a\*.*"
    
    C:\x>echo "C:\x\P\M\HOGE\*.*"
    "C:\x\P\M\HOGE\*.*"
    
[/code]

HOGEディレクトリなので、先頭の*を外したらおかしなことになりました。これはなぜ下記結果になるのですか？

[code]

    C:\for /r /d %a in (HOGE) do echo "%a\*.*"
    C:\x>echo "C:\x\P\M\HOGE\HOGE\*.*"
    "C:\x\P\M\HOGE\HOGE\*.*"
    
[/code]

* * *

**次に試したこと**  
任意の場所から実行できるようにしたかったのですが、

[code]

    for /r /d %a in (C:\xディレクトリ内の「任意の階層」にあるHOGEディレクリ) do echo "%a\*.*"
    
[/code]

Cドライブからのパスを指定すると、結果に何も表示されないのは何故ですか？

[code]

    for /r /d %a in (C:\x\*HOGE) do echo "%a\*.*"
    
    for /r /d %a in (C:\x*HOGE) do echo "%a\*.*"
    
[/code]


CC BY-SA 4.0
2019-11-24T00:37:05.563
60797
2019-11-24T12:07:05.780
2019-11-24T12:07:05.780
3060
7886
question
windows batch-file
「指定ディレクトリ」内の「任意の階層」にある「指定ディレクトリ名」内にある全ファイルを抽出したい


質問に直接答えていませんが、私が使っている方法を紹介します。

  1. 目的のパス(※１)を指定して`dir`を実行し、結果をリストファイル(例ではlist.txt)にリダイレクトする。
  2. リストファイルを使って`for`で各ファイルの情報を出力する。

※１ 例ではC:\x\P\M\HOGE\  
※２ 例ではlist.txt

例

[code]

    set LIST=list.txt
    set DP=C:\x\P\M\HOGE\
    dir /S /B "%DP%" > %LIST%
    for /F "delims= " %%I in ( %LIST% ) DO @echo %%~nxI %%~xI   %%~aI   %%~zI   %%~tI   %%~pI   %%~fI
    
[/code]

`delims=`の後ろはタブコードにしています。  
`echo`で出力する項目もタブコードで区切っています。理由は、表計算ソフトのシートに貼り付けることが多いのと、ファイル名に使えない（まはた滅多に使わない）文字で区切りたかったからです。

`for`の使い方は、`cmd`で`help for`を実行すると詳しい説明が出てきます。

* * *

findでフォルダを絞り込んだら質問された方の要望に近くなると思います。

[code]

    dir /S /B "%DP%" | find "\HOGE\"　> %LIST%
    
[/code]

* * *

私は指定フォルダ下の全ファイルをファイル出力し、その出力ファイルをnotepadで開く`bat`を作成しています。  
手作業ですが、notepadが立ち上がったら結果を全選択してクリップボードにコピー、表計算ソフトのシートに貼り付けて、オートフィルタで目的のファイルだけをしぼり込みます。  
しぼり込む対象が変わるたびに`bat`を実行するのは時間がもったいないからです。  
数万のファイルを出力することも度々あります。  
dirを使うので、UNCが使える環境なら共有された別マシンのフォルダの一覧も作成することができます。


CC BY-SA 4.0
2019-11-24T01:26:50.773
60798
2019-11-24T11:33:35.157
2019-11-24T11:33:35.157
35558
35558
60797
answer


**問：先頭の*を外したらおかしなことになりました。これはなぜ下記結果になるのですか？**  
おそらく、`/D`の指定と`()`の中にワイルドカードがあるかどうか、の組み合わせが原因でしょう。

`*`(ワイルドカード)がある場合は、そのワイルドカードを含む`ディレクトリ名`を検索して見つかったディレクトリ名を変数に入れる、指定にワイルドカードが無い場合は、指定されたディレクトリ配下の全ディレクトリに対して`()`内の文字列を付加して変数に入れる、という動作になっていると考えられます。

以下は FOR の HELP の抜粋です。

> FOR /D %変数 IN (セット) DO コマンド [コマンド パラメーター]
>
> セットがワイルドカードを含む場合は、ファイル名ではなくディレクトリ名  
>  の一致を指定します。
>
> FOR /R [[ドライブ:]パス] %変数 IN (セット) DO コマンド [コマンド パラメーター]
>
> [ドライブ:]パスから始めて、ツリーの各ディレクトリで FOR 文を実行し  
>  ます。/R の後にディレクトリが指定されていない場合は、現在の  
>  ディレクトリが使用されます。セットが単一のピリオド (.) である場合は、  
>  ディレクトリ ツリーの列挙だけを行います。

**問：Cドライブからのパスを指定すると、結果に何も表示されないのは何故ですか？**  
おそらく、開始位置のディレクトリパス名に、その指定の文字列がすべて追加されて、それに合うディレクトリ名が検索されるからでしょう。  
カレントディレクトリが`C:\x`だとしたら、以下の形で検索されるのでは？

> for /r /d %a in (C:\x\\*HOGE) do echo "%a\\*.*"
[code]

    C:\x\C:\x\*HOGE
    C:\x\P\C:\x\*HOGE
    C:\x\P\M\C:\x\*HOGE
    C:\x\P\M\HOGE\C:\x\*HOGE
    
[/code]

> for /r /d %a in (C:\x*HOGE) do echo "%a\\*.*"
[code]

    C:\x\C:\x*HOGE
    C:\x\P\C:\x*HOGE
    C:\x\P\M\C:\x*HOGE
    C:\x\P\M\HOGE\C:\x*HOGE
    
[/code]

* * *

**任意の場所から実行できるようにしたい** 場合は、`/r` と `/d`
の間にディレクトリ指定を入れることで実現できます。さらに検索結果については、ワイルドカード指定があるために`HUGAHOGE`とかもマッチする可能性があるわけで、それの対策が必要でしょう。  
`C:\x`から検索したい場合は、以下の様なコマンドになると思われます。

[code]

    for /r C:\x /d %a in (*HOGE) do if /i "%~nxa"=="HOGE" echo "%a\*.*"
    
[/code]

大文字小文字を厳密に比較する場合は`/i`は付けないでおきます。

そして見つかったディレクトリのリストを表示したいなら、`echo "%a\*.*"`を`dir %a`に変えれば良いでしょう。  
後で何かの処理に使うためにフルパスでファイルだけ抽出したいのならば、`dir /b/s/a-D %a
>>結果格納ファイルパス名`のような感じで記録しておけば良いと思われます。


CC BY-SA 4.0
2019-11-24T02:33:11.160
60801
2019-11-24T11:14:59.497
2019-11-24T11:14:59.497
26370
26370
60797
answer