質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.59%

Windows10のコマンドプロンプト上でできるCSVファイルの結合および行先頭へのファイル名追加

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 5,247

majin

score 10

 前提・実現したいこと

windows10のコマンドプロンプト上で実現可能な、
半角スペースを含むファイル名を持ったcsvファイルの結合(マージ)及び、
マージファイルの各先頭行にファイル名を出力したい。(可能なら拡張子抜きで)

非エンジニアの方が使用する前提でbatファイル化する想定です。
手前ではruby等で適当なscriptを書いて対応しているのですが、
毎回同じ依頼が来るため作業の簡略化したいです。

 発生している問題・エラーメッセージ

実現したいことは下記質問とほぼ同じです。
『コマンドプロンプトでのCSVファイルの結合』
https://teratail.com/questions/138642#reply-209800

ほとんどのファイルは結合できたのですが、
今回対応するファイル群にはファイル名に半角スペースが入っているものがあり、
上記の質問上にて回答されていた方のソースコードでは対応できませんでした。
例:「転職 東京.csv」「ランチ 渋谷.csv」みたいな感じのファイルです。わかる方はわかるかもしれませんが、GRCという順位取得ツールの出力ファイルです。

 該当のソースコード

Windows10 コマンドプロンプト

@echo off
set OPT="tokens=*"
(
for %%i in (*.csv) do call :SUB %%i
)>result.csv.out
pause
goto :EOF

:SUB
echo %1>CON
for /f %OPT% %%b in (%1) do echo %1,%%b
set OPT="tokens=* skip=1"
goto :EOF

 追加補足

また、上記のコードだとファイル名がそのまま先頭行に入っているので、可能なら追記するファイル名の拡張子も削除した状態で出力したいです。

手前勝手な質問で申し訳ありませんが、お力添えいただけますとありがたいです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+2

VBScript で作ってみました。
CSVファイルをスクリプトにドロップします。

Option Explicit
Dim objF,args,i,outf,outp,outs,inp
Set objF = CreateObject("Scripting.FileSystemObject")
Set args = WScript.Arguments
If args.count = 0 Then
  MsgBox "CSVファイルをドロップしてください。"
  WScript.Quit
End If
outf = objF.GetParentFolderName(args.item(0)) & "\hoge.csv"
Set outp = objF.OpenTextFile(outf,2,True)
For i = 0 To args.count - 1 Step 1
  If Ucase(objF.GetExtensionName(args.item(i))) = "CSV" Then
    Set inp = objF.OpenTextFile(args.item(i),1)
    Do Until inp.AtEndOfStream
      outp.WriteLine objF.getBaseName(args.item(i)) & "," & inp.ReadLine
    Loop
    inp.Close
    Set inp = Nothing
  End If
Next
outp.Close
Set outp = Nothing
Set objF = Nothing
MsgBox args.count & "ファイルを結合しました。"


スクリプト名は hogehoge.vbs みたいな感じで保存します。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/09 16:26

    おお!ありがとうございます。
    こちら問題なく動きました!
    VBScriptというものを初めて知りました。

    キャンセル

+1

サブルーチンに渡す際に "" で囲ってあげましょう。
受け取る時に %~1 のように ~ つけるとダブルクォーテーションを取り除きます。
ファイル名から拡張子を取り除く場合は %~n1 のように ~n を付けます。

全体の処理がわからないので完動コードかはわかりませんが、以下参考になさってください。

@echo off
set OPT="tokens=*"
(
for %%i in (*.csv) do call :SUB "%%i"
)>result.csv.out
pause
goto :EOF

:SUB
echo "%~n1">CON
for /f %OPT% %%b in ("%~1") do echo "%~1",%%b
set OPT="tokens=* skip=1"
goto :EOF

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/09 15:02 編集

    ありがとうございます!
    > 受け取る時に %~1 のように ~ つけるとダブルクォーテーションを取り除きます。
    > ファイル名から拡張子を取り除く場合は %~n1 のように ~n を付けます。
    大変勉強になりました。

    頂いたソースを参考にごちゃごちゃ書き直してみたのですが、
    半角スペースを含むファイルは処理が通りません。
    ソース全体

    ```
    @echo off
    set OPT="tokens=*"
    (
    for %%i in (*.csv) do (
    call :SUB "%%i"
    )
    )>result.csv.out
    pause
    goto :EOF

    :SUB
    echo FileLoad : "%~1">CON
    for /f %OPT% %%b in (%~1) do (
    echo %~n1,%%b
    )
    set OPT="tokens=* skip=1"
    goto :EOF
    ```

    おそらくSUBのfor文のところでファイルを読み込めていないのだと思います。

    ```for /f %OPT% %%b in (%~1)```

    また、頂いたソースのようにSUBのfor文の箇所で読み込むファイル名を、
    下記のように""で囲み、~で回避しようとすると

    ```for /f %OPT% %%b in ("%~1")```

    %%bにファイル名が入ってしまうようで、
    出力が「ファイル名,ファイル名.csv」となってしまいます。
    加えて何故か半角スペースを含まないファイルは読み込まなくなります。

    結合しようとしているファイルの例も下記においておきます。
    ファイル名:「求人 名古屋.csv」

    ```
    順位,Google タイトル,Google URL,Google スニペット
    1,「求人 名古屋」で1位のサイト,http://1.com,サイトの説明
    2,「求人 名古屋」で2位のサイト,http://2.com,サイトの説明
    3,「求人 名古屋」で3位のサイト,http://3.com,サイトの説明
    4,「求人 名古屋」で4位のサイト,http://4.com,サイトの説明
    5,「求人 名古屋」で5位のサイト,http://5.com,サイトの説明
    ```

    ファイル名:「求人.csv」

    ```
    順位,Google タイトル,Google URL,Google スニペット
    1,「求人」で1位のサイト,http://1.com,サイトの説明
    2,「求人」で2位のサイト,http://2.com,サイトの説明
    3,「求人」で3位のサイト,http://3.com,サイトの説明
    4,「求人」で4位のサイト,http://4.com,サイトの説明
    5,「求人」で5位のサイト,http://5.com,サイトの説明
    ```

    ご助言いただけますと助かります。
    ※もしかして返信に対する返信だと```表記とか使えない?

    キャンセル

  • 2018/11/09 15:13

    出力したいファイルは以下ですか?

    ファイル名,順位,Google タイトル,Google URL,Google スニペット
    求人 名古屋.csv,1,「求人 名古屋」で1位のサイト,http://1.com,サイトの説明
    求人 名古屋.csv,2,「求人 名古屋」で2位のサイト,http://2.com,サイトの説明
    求人 名古屋.csv,3,「求人 名古屋」で3位のサイト,http://3.com,サイトの説明
    求人 名古屋.csv,4,「求人 名古屋」で4位のサイト,http://4.com,サイトの説明
    求人 名古屋.csv,5,「求人 名古屋」で5位のサイト,http://5.com,サイトの説明
    求人.csv,1,「求人」で1位のサイト,http://1.com,サイトの説明
    求人.csv,2,「求人」で2位のサイト,http://2.com,サイトの説明
    求人.csv,3,「求人」で3位のサイト,http://3.com,サイトの説明
    求人.csv,4,「求人」で4位のサイト,http://4.com,サイトの説明
    求人.csv,5,「求人」で5位のサイト,http://5.com,サイトの説明

    キャンセル

  • 2018/11/09 15:25

    上記でも可ですが、可能なら下記のようにファイル名の拡張子は除きたいです。

    ファイル名,順位,Google タイトル,Google URL,Google スニペット
    求人 名古屋,1,「求人 名古屋」で1位のサイト,http://1.com,サイトの説明
    求人 名古屋,2,「求人 名古屋」で2位のサイト,http://2.com,サイトの説明
    求人 名古屋,3,「求人 名古屋」で3位のサイト,http://3.com,サイトの説明
    求人 名古屋,4,「求人 名古屋」で4位のサイト,http://4.com,サイトの説明
    求人 名古屋,5,「求人 名古屋」で5位のサイト,http://5.com,サイトの説明
    求人,1,「求人」で1位のサイト,http://1.com,サイトの説明
    求人,2,「求人」で2位のサイト,http://2.com,サイトの説明
    求人,3,「求人」で3位のサイト,http://3.com,サイトの説明
    求人,4,「求人」で4位のサイト,http://4.com,サイトの説明
    求人,5,「求人」で5位のサイト,http://5.com,サイトの説明

    キャンセル

+1

こういう処理ならperlが圧倒的に楽なんですよね。

https://www.nkozawa.com/blog/archives/3935
こちらで紹介されているシステムを使うとperlスクリプトを簡単にexeファイル化できて、perlの知識皆無の人にも使ってもらうことができます。

rubyを使われているということですから、perlの敷居はそんなに高くないですよね。ひとつのオプションとして検討してはいかがでしょう。

perlスクリプトはこんな感じになります。

use strict;
use File::Basename;

# options
my @files = <~*.csv>;
my $outfile = "merged.txt";

open(my $fho, ">", $outfile) or die "Cannot open $outfile";

# header
open(my $fhi, "<", $files[0]);
$_ = <$fhi>;
print {$fho} "filename\t", $_;
close $fhi;

# contents
foreach my $file (@files){
  my $filename = fileparse($file, '\..*$');
  open(my $fhi, "<", $file);
  $_ = <$fhi>; # skip header
  while(<$fhi>){
    print {$fho} "$filename\t", $_;
  }
}
close $fho;

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/09 16:56

    ありがとうございます!
    Perlも多少は分かるので、こちら参考にさせていただきます。

    キャンセル

+1

空白を含んだファイル名を対象にするのはめんどくさいので、必要の無いときは考えていませんでしたが、質問者以外が参照する事を考えると、考えて置いた方が良かったですね。
とはいえ、ファイル中の行頭に;があるケースとか考慮すると、どんなケースにも使えるスクリプトは無理なんですが。

引用符で囲んだファイル名を読むときはusebackqが必要です。

@echo off
set OPT="usebackq tokens=*"
(
for %%i in (*.csv) do call :SUB "%%i"
)>result.csv.out
pause
goto :EOF

:SUB
echo FileLoad : %1 >CON
for /f %OPT% %%b in (%1) do echo %~n1,%%b
set OPT="usebackq tokens=* skip=1"
goto :EOF

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/12 09:23

    返信遅くなりました!
    わざわざありがとうございます!
    こちら期待通りの動きになっております!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • CSVに関する質問
  • Windows10のコマンドプロンプト上でできるCSVファイルの結合および行先頭へのファイル名追加