Batファイルについて教えてください。

複数階層にまたがっているエクセルファイルをBatファイルでコピー、又は、移動させたいのです。コピー、移動させたいファイルはファイル名の頭(重複しないIDになっている)を拾ってリストにしてあります。エクセルファイルが複数のフォルダに入っているので、最上階層のフォルダでbatファイルを実行できればと思っていますが。

回答の条件
  • 1人5回まで
  • 13歳以上
  • 登録:2011/10/29 15:12:49
  • 終了:2011/11/01 19:10:57

ベストアンサー

id:language_and_engineering No.1

lang_and_engine回答回数170ベストアンサー獲得回数632011/10/29 20:34:13

できました。実行結果も添付します。

事前の状態:


D:\temp\battest>tree /f
フォルダ パスの一覧
ボリューム シリアル番号は 6C76-71D3 です
D:.
│  移動.bat
│  移動対象の先頭IDのリスト.txt
│
├─コピー元
│  │  hoge.xlsx
│  │  移動対象1_fuga.xlsx
│  │
│  └─a
│          fuga.xlsx
│          移動対象2_hoge.xlsx
│
└─コピー先


D:\temp\battest>type 移動対象の先頭IDのリスト.txt
移動対象1
移動対象2

移動.bat:


@echo off

rem 変数定義
set IDLIST=移動対象の先頭IDのリスト.txt
set FROM_DIR=コピー元
set TO_DIR=コピー先

rem カレントを変数に保持
for /F "usebackq" %%i in (`cd`) do (
  set BAT_DIR="%%i"
)

rem 開始
echo 「%FROM_DIR%」内のファイルを全チェックします。
cd "%FROM_DIR%"

rem 先頭IDごとに
for /f "usebackq" %%n in (`type %BAT_DIR%\%IDLIST%`) do (
  echo --------- 先頭IDが「%%n」であるようなファイルを移動します。 --------- 
  
  rem 発見したファイルごとに
  for /f "usebackq" %%m in (`dir /s /b %%n*.xlsx`) do (
    echo 移動対象ファイル「%%m」を発見しました。コピーします。
    
    rem コピー実行
    copy /y %%m %BAT_DIR%\%TO_DIR%\
  )
)

rem 終了
echo --------- 全コピーが完了しました。コピー結果: --------- 
dir /b %BAT_DIR%\%TO_DIR%
echo -------------------------------------------------------- 

pause

実行結果:


「コピー元」内のファイルを全チェックします。
--------- 先頭IDが「移動対象1」であるようなファイルを移動します。 ---------
移動対象ファイル「D:\temp\battest\コピー元\移動対象1_fuga.xlsx」を発見しました。
コピーします。
        1 個のファイルをコピーしました。
--------- 先頭IDが「移動対象2」であるようなファイルを移動します。 ---------
移動対象ファイル「D:\temp\battest\コピー元\a\移動対象2_hoge.xlsx」を発見しました
。コピーします。
        1 個のファイルをコピーしました。
--------- 全コピーが完了しました。コピー結果: ---------
移動対象1_fuga.xlsx
移動対象2_hoge.xlsx
--------------------------------------------------------
続行するには何かキーを押してください . . .

その他の回答(2件)

id:language_and_engineering No.1

lang_and_engine回答回数170ベストアンサー獲得回数632011/10/29 20:34:13ここでベストアンサー

できました。実行結果も添付します。

事前の状態:


D:\temp\battest>tree /f
フォルダ パスの一覧
ボリューム シリアル番号は 6C76-71D3 です
D:.
│  移動.bat
│  移動対象の先頭IDのリスト.txt
│
├─コピー元
│  │  hoge.xlsx
│  │  移動対象1_fuga.xlsx
│  │
│  └─a
│          fuga.xlsx
│          移動対象2_hoge.xlsx
│
└─コピー先


D:\temp\battest>type 移動対象の先頭IDのリスト.txt
移動対象1
移動対象2

移動.bat:


@echo off

rem 変数定義
set IDLIST=移動対象の先頭IDのリスト.txt
set FROM_DIR=コピー元
set TO_DIR=コピー先

rem カレントを変数に保持
for /F "usebackq" %%i in (`cd`) do (
  set BAT_DIR="%%i"
)

rem 開始
echo 「%FROM_DIR%」内のファイルを全チェックします。
cd "%FROM_DIR%"

rem 先頭IDごとに
for /f "usebackq" %%n in (`type %BAT_DIR%\%IDLIST%`) do (
  echo --------- 先頭IDが「%%n」であるようなファイルを移動します。 --------- 
  
  rem 発見したファイルごとに
  for /f "usebackq" %%m in (`dir /s /b %%n*.xlsx`) do (
    echo 移動対象ファイル「%%m」を発見しました。コピーします。
    
    rem コピー実行
    copy /y %%m %BAT_DIR%\%TO_DIR%\
  )
)

rem 終了
echo --------- 全コピーが完了しました。コピー結果: --------- 
dir /b %BAT_DIR%\%TO_DIR%
echo -------------------------------------------------------- 

pause

実行結果:


「コピー元」内のファイルを全チェックします。
--------- 先頭IDが「移動対象1」であるようなファイルを移動します。 ---------
移動対象ファイル「D:\temp\battest\コピー元\移動対象1_fuga.xlsx」を発見しました。
コピーします。
        1 個のファイルをコピーしました。
--------- 先頭IDが「移動対象2」であるようなファイルを移動します。 ---------
移動対象ファイル「D:\temp\battest\コピー元\a\移動対象2_hoge.xlsx」を発見しました
。コピーします。
        1 個のファイルをコピーしました。
--------- 全コピーが完了しました。コピー結果: ---------
移動対象1_fuga.xlsx
移動対象2_hoge.xlsx
--------------------------------------------------------
続行するには何かキーを押してください . . .

id:jak-san No.2

jak-san回答回数11ベストアンサー獲得回数22011/10/30 21:16:49

コピーしたいファイル名の先頭(=ID)が各行に1つずつ列記されているファイルをlist.txtとします。

コピー先はD:\testとします。同一ファイル名の重複があった場合は上書きコピーされますので、それが困る場合はどうしたいかコメントしてください。


for /F "delims=" %%d in ( list.txt ) do for /F "delims=" %%f in ('dir /s /b "%%d*.xls"') do copy "%%f" d:\test
id:language_and_engineering No.3

lang_and_engine回答回数170ベストアンサー獲得回数632011/10/31 01:01:26

コメント欄での要件追加に伴い,改めて回答させて頂きます。


>重複するファイル名が存在する場合、何を優先して拾っているのでしょうか。

回答1のコードは,「ファイルが見つかった順」に上書き保存しています。


>重複したものも全て拾うことはできますでしょうか。

そのようなバッチを作り,下記エントリに掲載しておきました。

実行結果のログ付きです。

「ファイル名の重複防止機能付き」とあるように,

重複ファイルはファイル名の末尾に 2, 3, ...と番号が振られるようにしてあります。

bat中でforループをネストし,サブルーチンを呼び出して,条件付きファイル検索の結果を一斉コピーしよう (ファイル名の重複防止機能付き)

http://d.hatena.ne.jp/language_and_engineering/20111030/p1

お試しください。

  • id:saya667
    language_and_engineeringさん
    ありがとうございます。
    しかし、難しすぎてこれをどうやって使うのか自体分りません。
    移動batをバッチファイルに貼り付ければいいんでしょうか。

  • id:language_and_engineering
    saya667様

    少し詳しく仕様をご説明します。


    最初の tree /f コマンドの実行結果は,ファイルやフォルダの構成を示しています。
    いわば,このバッチファイルを利用するために前提となるファイル構成です。

    ここでは,下記の4つが同じ階層に存在する事を想定しています。

    1:移動.bat
    2:移動対象の先頭IDのリスト.txt
    3:コピー元フォルダ(ここでは「コピー元」)
    4:コピー先フォルダ(ここでは「コピー先」)


    移動.batというファイルを作成し,上記回答中の
    「移動.bat:」以降のソースコードを貼り付けて保存してください。

    もし「コピー先」「コピー元」のフォルダ名を変えたい場合は,
     set FROM_DIR=コピー元
    などの行を編集し,該当するフォルダ名に書き換えて下さい。


    typeコマンドは,ファイルの中味を表示するコマンドです。
    質問文中に
    「コピー、移動させたいファイルはファイル名の頭(重複しないIDになっている)を拾ってリストにしてあります。」
    とありますが,ここではそのリストが
     移動対象の先頭IDのリスト.txt
    という名前のファイルにしてあります。


    「コピー元」フォルダは,質問文中の
     「最上階層のフォルダ」
    の一つ上のフォルダに相当します。


    「コピー先」フォルダも,あらかじめ作っておいてください。


    上記の4要素がそろった状態で,「移動.bat」をダブルクリックして実行してください。

    実行すると,上記回答中の「実行結果:」のような結果が表示されます。
    完了すると「コピー先」フォルダの中に,欲しいファイルが収集されています。
  • id:saya667
    language_and_engineeringさん

    何度もすみません。
    やってみましたが、File Not Foundとなってしまいます。
    4つを同じ階層にしているので、ドライブやパスの指定は必要ないですよね?
    また、移動batの中のソースを貼り付ける際には、日本語のコメントもそのまま貼り付けていいのですよね?
    すみません。低レベルな質問で。
  • id:saya667
    language_and_engineeringさん
    追記です。
    事前の状態、に書かれている
    D:\temp\battest>tree /f
    ですが、4つのファイルとフォルダもDドライブに入れる必要があるということでしょうか。因みに私のPCではDドライブは見えません。
  • id:language_and_engineering
    saya667様


    どうやら,かえって手間をかけてしまっているようで,申し訳ないですね。

    低レベルな質問とお感じになる必要はありません。

    技術者がいくら上手なプログラムを書いたとしても,
    もしお客様に「使いやすい!便利だ」と感じて頂けないとしたら,
    それはプログラマ側の名折れですので。


    >4つを同じ階層にしているので、ドライブやパスの指定は必要ないですよね?

    ないはずです。
    ※ただし,共有フォルダやネットワークドライブだと「cd」コマンドが動作しないケースがあるため,「pushd」に書き換える必要がありますが。


    >また、移動batの中のソースを貼り付ける際には、日本語のコメントもそのまま貼り付けていいのですよね?

    はい。
    batファイル中には,rem文で日本語コメントを記載できます。


    >4つのファイルとフォルダもDドライブに入れる必要があるということでしょうか。

    いいえ。
    私個人がテスト用に「D:\temp\battest」というフォルダ内で動作確認しただけです。
    ファイルの配置方法が正しければ,フォルダの具体的なパスに関わりなく,正常に動作するはずです。



    一番疑わしい可能性ですが…

    for /f "usebackq" %%m in (`dir /s /b %%n*.xlsx`) do (

    という行は,「.xlsx」という拡張子のファイルを検索しています。
    もしお手元の環境でOffice2003などをお使いの場合は,検索対象の拡張子を変えて

    for /f "usebackq" %%m in (`dir /s /b %%n*.xls`) do (

    のように書き換える必要があります。
    お試しください。


    もしそれでもだめでしたら,問題を切り分けるために,
    実行結果のログを丸ごと or 一部でもいいですので,ご提示下さい。
    回答欄の「実行結果:」以降に記載されているような感じの内容です。

  • id:saya667
    language_and_engineeringさん

    ご親切に有難うございます。仰る通りエクセルの拡張子をxlsにしたら大丈夫でした。
    ですが、「コピー元」に入っているのはコピーされましたが、他のフォルダ名になっているものは拾ってくれません。「コピー元」の下の階層にはA~Z社(各会社名)までの会社毎のフォルダになっており、A~Zの中までみて拾いたいのですが。
    可能でしょうか。

  • id:language_and_engineering
    saya667様

    会社毎のフォルダのフォルダ名に,スペースが入っているのかもしれません。
    その場合,BATの内容に修正が必要です。


    修正前:

    rem 発見したファイルごとに
    for /f "usebackq" %%m in (`dir /s /b %%n*.xls`) do (
    echo 移動対象ファイル「%%m」を発見しました。コピーします。

    rem コピー実行
    copy /y %%m %BAT_DIR%\%TO_DIR%\
    )


    修正後:

    rem 発見したファイルごとに
    for /f "usebackq delims=" %%m in (`dir /s /b %%n*.xls`) do (
    echo 移動対象ファイル「%%m」を発見しました。コピーします。

    rem コピー実行
    copy /y "%%m" %BAT_DIR%\%TO_DIR%\
    )


    いかがでしょうか。
  • id:saya667
    language_and_engineeringさん

    有難うございました。
    これまた仰るようにフォルダ名にスペースが入っていたためでした。

    最後にもう一つだけ教えてください。
    重複するファイル名が存在する場合、何を優先して拾っているのでしょうか。テストしたところ、更新日の新旧でもなかったようなのですが。

    重複しないIDと書いたのはそもそも私ですが、実は実際のファイルでは重複が存在してしまう時があります。重複したものも全て拾うことはできますでしょうか。

    本当に図々しく何度もすみません。
  • id:saya667
    language_and_engineeringさん


    大変な作業をお願いしたみたいです。
    今から会社なので、会社にて検証します。
    また結果お知らせします。
    本当に有難うございます。

  • id:saya667
    language_and_engineeringさん

    会社でテストしています。
    ローカルで作業する分には大丈夫なのですが、ネットワーク上だと下記のコメントが出て拾えません。

    「"コピー元"」内のファイルを全チェックします。
    The system cannot find the path specified.
    全コピーが完了しました。コピー結果
    The system cannot find the file specified.

    ネットワーク上では使用できないのでしょうか。
    すみません。またまた。。


  • id:language_and_engineering
    saya667様

    上のコメントで

    >※ただし,共有フォルダやネットワークドライブだと「cd」コマンドが動作しないケースが
    >あるため,「pushd」に書き換える必要がありますが。

    と書きましたが,そこにひっかかったようです。

    リンク先の掲載内容は更新されました。
    現在は,ネットワーク上の共有フォルダにも対応しています。
  • id:saya667
    language_and_engineeringさん

    他力本願な私が悪いのですが、もううんざりされているのではと少し心配しています。
    ネットワーク対応版で試したもののやはり出来なかったのです。
    明日再度会社のネットワークで検証してみます。
    今回私がbatと言ったのはそれしか知らなかったからですが、WSH/JScriptのバッチでコーディングすればかなり楽だったろう、とのコメントを読み、申し訳なく思っています。
    本当にすみません。
  • id:language_and_engineering
    saya667様

    >うんざりされているのではと少し心配しています。
    >申し訳なく思っています。

    そのように思われる必要はありません。


    ただ現実問題として,私個人として本業もありますので
    残念ながらこれ以上のサポートは難しいです。

    もし時間があれば,最後までお付き合いしたいところなのですがね。



    私からの最初の回答の執筆後,saya667様より追加要件の提示(仕様変更)が3回ありました。

    -(追加1)Officeのバージョンが明示されていなかったため,Excelファイルの拡張子をxlsxからxlsに変える必要があった。
    -(追加2)ファイル名が重複した場合の挙動が明示されていなかったが,その場合の詳細な挙動も作りこんだ。
    -(追加3)実行環境が明示されていなかったため,共有フォルダ上では実行できない旨をあらかじめお伝えしてあったが,共有フォルダ上でも実行できるように作り替えた。

    当方としては,ベストエフォートで対応させていただきました。


    ※仕様変更が発生するという事は,追加工数(人日)が発生するという事です。
     もしも,あらかじめこれら3点を「前提事項」として質問内容に最初から含めて頂ければ,
     回答者は「質問者が欲しい物」を誤解なくピンポイントで一発で作る事ができ,
     ロスが減り,双方がハッピーになります。
     今後の質問投稿時のご参考になさってください。



    現状では,プログラムとしてはこれでもう完成している状態です。
    なので,あえて今からWSH/JScript等で作り直す必要はありません。

    この状態でもまだダメ,となると,エラーの原因を知るためには
    そちらの環境をかなり詳しく把握しないといけません。

    状況を把握できるよう,このbatファイルは動作ログを多めに出力しています。
    もしプログラムの修正が必要な場合,プログラマはログの内容を頼りに状況を判断し,
    何が原因で正しく動作しないのかを判断して修正してゆく必要があります。


    とはいえ,saya667様は,この場でログを提示することは不可能でしょう。
    なぜならそちらの実行環境のフォルダ名には「取引先の会社名」などの機密内容が含まれますから,
    インターネット上に気軽にコピペするわけにはいきません。

    なので,残念ながら,こういった公開掲示板でサポートできる事柄には限界があるという事になります。



    私が本質問に回答した理由・動機についてですが,質問文を拝読した際
    「こんな複雑な要件を,BATのプログラムだけで解決することが可能なのだろうか?もしできたら凄かろうな。」
    という好奇心を感じました。

    それでたまたま,その時は少し時間があったので,人助けの半分,
    自分の腕試しとしてプログラミングに取り掛かったまでです。
    (掲示板等に回答する技術者の動機の大半は,そんなところでしょう。)

    もし最終的にお役に立たなかったのであれば,ポイントは要りませんので。



    最後に,この状況で採用できる代替案をいくつかご提案します。
    どれかのアイデアがお役にたてば幸いです。

    -(代案1)ローカルでは動くが,ネットワーク上では動かない。という事であれば,
     いったんネットワーク上のファイルをごっそりローカルにコピーして,
     ローカルで実行すれば済むのでは?

    -(代案2)本プログラムは,ログ出力やコメントを多量に盛り込んであります。
     その目的は
      ・エラーが起きた時の原因を容易に究明できるようにするため。
      ・プログラムに詳しくない人であっても,ソースコードの内容を容易に理解できるようにするため。
     のように保守性を向上させる事です。
     ですので,今あるプログラムを基にしてBATの勉強をしたり,改変をしたりしやすいようになっています。
     そのメリットを活用して,ご自分で改変にトライしてみるか,周りの詳しそうな人にトライしてもらうのはいかがでしょうか?

    -(代案3)この質問をオープンしておけば,誰か親切な方が,
     ちゃんと動くバッチを新たに投稿して下さるかもしれません。その期待も捨てないでおく事ができます。



    お役に立てず,誠に残念です。

    それでは。
  • id:language_and_engineering

    -(代案4)マイコンピュータからネットワークドライブを割り当てることによって,
     共有フォルダを疑似的にローカルフォルダとして扱う。
     その上で該当バッチを実行してみる。
  • id:saya667
    language_and_engineeringさん

    ご連絡が遅くなりました。
    やはりどうしてもネットワーク上では出来ませんでした。
    色々ご教授いただき、またお骨折り頂き有難うございました。


この質問への反応(ブックマークコメント)

トラックバック

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません