コマンドラインで脱Excel手作業 フォルダ内の全ファイルでドババンとソートや検索を行う(後編)マウスのいらないコマンドプロンプトの世界

データを順番通りに並べ替えたい場合、Excelを起動して、対象となるデータをシートに読み込んで、[並べ替え]コマンドを実行しているのではないだろうか。ただ、ファイルが複数に分かれていると作業が面倒だ。コマンドを使えば、ファイルを1つにまとめて並べ替えるのも簡単だ。

» 2021年03月25日 05時00分 公開
[竹内充彦]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

コマンドを使えば複数ファイルのデータをまとめることも簡単 コマンドを使えば複数ファイルのデータをまとめることも簡単
データの並べ替えが必要な場面は意外と多い。Excelを起動して、ソートを実行することも多いと思うが、複数ファイルに分かれている場合は少し面倒だ。コマンドを使えば、複数ファイルをまとめて、ソートするのも簡単だ。

複数のデータファイルを1つに合わせて並べ替える

 マウスのいらないコマンドプロンプトの世界「コマンドラインで脱Excel手作業 フォルダ内の全ファイルでドババンとソートや検索を行う(前編)」では、sortやfindコマンドを使って、単一のファイルに収められたデータの単純な並べ替え作業を行った。しかし、元データが常に1つのファイルに収められた形とは限らない。幾つかのファイルを1つにまとめたり、複数ファイルから目的のデータを集めてきたりして、並べ替えを行わなければならないという場合もある。

 そこで今回は、複数のファイルからデータを読み取り、並べ替える方法を紹介する。

 マウスのいらないコマンドプロンプトの世界「コマンドラインで脱Excel手作業 フォルダ内の全ファイルでドババンとソートや検索を行う(前編)」でも述べたが、複雑なデータの並べ替えや抽出を行うなら「Microsoft Excel(エクセル)」を使った方が効率的だ。しかし、元データが固定長のフィールドを持ち、単純な並べ替えを行うのであれば、Windows OSのコマンドを利用した方が手っ取り早い。

 元データが複数のファイルに分かれている場合でも、データ構造や処理内容が条件に合致していれば、Excelを開いて作業を行うよりも、sortコマンドを使った方が早いだろう。ただし、sortコマンドには弱点もある。それを今回は乗り越えていきたい。

【今回のミッション】

 また上司から仕事を頼まれた。

 「昨日、全社で開催したボーリング大会のデータが届いたから。キミから指摘のあった点を参考に書式を改善し、スコアを名前より左に置いて点数で並べ替えできるようにして、所属と別に拠点名も追加したぞ。ただ、ファイルは東京本社、大阪支社、福岡支社の各拠点から届いたばかりで、3つに分かれたまま[score]フォルダの中に置いたよ。で、この3つのデータを1つにまとめて、スコアで並べ替えて社内総合スコアランキングを作ってほしいんだな」

 何だかボーリング大会ばかりしているようだが、大丈夫なのか、この会社……、という不安はひとまず置いておいて、つまりこういうことだ。

データ形式とファイルの構成 データ形式とファイルの構成
「tokyo.txt」「osaka.txt」「fukuoka.txt」の3つのファイルに分かれているが、これらを1つにまとめて、全体をスコア順に並べ替えたい。

データ形式と各ファイルの内容 データ形式と各ファイルの内容
元データのフィールドは、スコア、拠点名、部署名、社員番号、名前となった。

 では早速、取り掛かろう。


融通のきかないsortコマンドを小技で生かす

 並べ替えの基準は「スコア」に変更されたが、その方法は前回紹介した。今回のポイントは、3つのファイルをまとめて扱うというところだ。

 [score]フォルダの下にある「tokyo.txt」「osaka.txt」「fukuoka.txt」という3つのファイルの全てのデータを合わせて並べ替えるということで、まず思い付くのは次のようなコマンドラインではないだろうか。

sort /r score\*.txt > members_rank.txt[Enter]

すぐに思い付く3つのファイルを合わせて並べ替えるコマンド

 少し横道にそれるが、「score\*.txt」という記述は、「カレントフォルダの下の[score]フォルダにある拡張子が『txt』のファイル全て」という意味だ。つまり[score]フォルダの親フォルダ(1つ上のフォルダ)をカレントフォルダとして作業している。「[score]フォルダをカレントフォルダにして、作業すれば余計な記述が減るのに」と思うかもしれないが、そうしない理由は後述する。

 さて本題に戻ろう。sortコマンドは、引数に入力ファイルを複数並べて記述したり、ワイルドカードを使って複数のファイルを一括指定したり、といったことができない。

sortコマンドの引数に複数のファイルを指定すると…… sortコマンドの引数に複数のファイルを指定すると……
複数のファイル名指定やワイルドカードによる一括指定を試みても、エラーメッセージが返ってきて、sortコマンドは正しく実行されない。これは困った。

 では、どうすればよいのだろうか。幾つか方法はあるが、最も手軽なのは標準入力からデータを読み込ませるという方法だ。

 具体的には、別のコマンドで複数のファイルを1つにまとめる下処理をして、その結果をパイプライン経由でsortコマンドに渡せばいい(パイプラインについては「コピペの連続はつらいよ ファイルの一覧を文書に取り込む!」参照)。例えば、「ファイルの内容を表示する」というシンプルなコマンド「type」を使って、次のようにすれば、複数のファイルをまとめてsortコマンドに渡し、並べ替えることができる。

type *.txt | sort /r  > members_rank.txt[Enter]

typeコマンドを使って複数のファイルをまとめるコマンド

typeコマンドの結果をsortコマンドに渡す(1) typeコマンドの結果をsortコマンドに渡す(1)
typeは入力ファイルを出力するだけというシンプルなコマンドだ。パイプラインと組み合わせれば、複数ファイルを連結してsortコマンドに渡すことができる。
typeコマンドの結果をsortコマンドに渡す(2) typeコマンドの結果をsortコマンドに渡す(2)
出力した結果をmoreコマンドで表示してみる。3つのファイルのデータがスコア順に並べられている。

 前回紹介したfindコマンドも、typeと同様、複数のファイルを扱えるため、例えば3つのファイルから指定した検索語を含む行を集めてきてsortコマンドに渡すという場合は、複数ファイルからのデータの読み込みをfindコマンドが担ってくれる。3つのファイルから営業部のメンバーを抜き出して、並べ替えるなら次のように指定すればよい。

find "営業部" score\*.txt | sort /r > members_sales_rank.txt[Enter]

複数のファイルから営業部のメンバーだけを抜き出して並び替えるコマンド

なぜデータが置いてあるフォルダで作業しないのか?

 これまで、この連載ではデータを置くフォルダで作業をしてきた。しかし今回はデータを置くフォルダ(今回は[score]フォルダ)の1つ上のフォルダで作業を行っている。

 その理由は、元データが保存されているファイルと結果を保存するファイルが混在してしまうのを避けるためだ。コマンドの入力例で出力先のファイルに拡張子が「.txt」のファイルを指定しているが、これが入力データと同じフォルダに作成されてしまうと、次回、別の処理を行いたくなったときに「*.txt」に含まれてしまい、正しい処理が行えなくなるのだ。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。