多数のファイルを処理する場合の工夫

xargsとGNU Parallelの個別の解説記事や、比較の解説記事は多いようだが、両者を組み合わせて使うと便利であることに気が付き、その解説は少なくとも日本語では見つからないので、以下に解説。

# 多数のファイルを処理する場合の工夫


- ここでは「多数のファイルを処理する場合の工夫」と書いたが、ここには分かり安い例示はない。
    - 例示が大きくなりがちなために、例を載せるのがやや困難なため。
    - 従って、下記のコマンド例を実行すれば意味が分かって、cheat sheetのように後で読み返しやすい様に、要点のみを記す。
- 下記は、あくまで__数万個__のファイルを対象にする場合である。
    - 数百万個もある場合は、下記の方法だと、各コマンドの起動が10ミリ秒であっても、計算が1日(86400秒)程度かかる。
    - そのような場合は、各コマンドが、数百個のファイルを一度に処理するように工夫すれば良い。そうすると、場合によっては、ここに書いてあるノウハウが再び役に立つであろう。

## 下記の状況を仮定する

1. 1個のディレクトリに__数万個のデータファイル__が存在する。
2. 何かの処理を手際よく処理したい。
3. 再現性を高い状態にして、保守性を高めたい。

## 数万個のファイルが1個のディリクトリにある場合の難点

- `ls` は何かを表示するまでの時間がかかる。
    - 比較すると`echo *` が何倍も高速。
- `less *`とすると`too long`などという警告が出て動かない。
    - これは、`echo * | xargs -n 1000 less ` で対処可能。

## その場合の対処法

- シェルの`for`句を使う — 繰り返し処理の指定が簡単に書ける。
  - シェルのfor句の簡単な例: ```for i in `seq 10` ; do echo $i ; done ```
- GNU Parallelを使う — プロセスの並列化が容易に出来て、処理が何倍も速くなる。
  - インストールして、コマンドの```parallel```を用いる。
  - 例えば次の様な使い方をする。
      - ```echo * | xargs -n1000 | parallel -C ' ' wc ```
      - よく使われているかも知れない使い方: 
          - `:::`や`::::`を使った構文の方がもっと基本的かもしれない。
          - `{}`や`{1}`などを使った書き方も要マスター。
      - しかし、下記で書いたようなことが、私には必要ではあった。
          - 上記の状況への対処に、どうやら xargsのみだと何かが足りない。
          - parallelを使うと一見複雑だが、最も簡潔そうである。

 
- Makefileを使う — 保守性と再現性が高まる。
  - 複数の処理にそれぞれ名前を付けて、必要な時に必要な処理が出来る。
     - `make proc1 proc2` などを実行すれば良い。
  - ひとつのファイルに、それらの複数の処理内容を書けるので、保守が楽。
     - ただし、シェルのコマンド文中の`$i` は`$$i`と書き換えたりなどの工夫が厄介かも。


## parallelとシェルのfor句を組み合わせる

1. for文と組み合わせない例(#) :
    -  `seq 20 | xargs -n8 | parallel -C ' ' echo`
2. for文を組み合わせる例: 
    - `seq 20 | xargs -n8 | parallel -C ' ' for i in {} \; do echo \$i \; done`。
    - 上記では、次の様な書き換えが必要となった。
         - `$`と`;`をエスケープする。parallelに渡す前に直接シェルに解釈させないため。
         - `|`,`"`,`(`,`)`,`<`,`>`,`'`などもエスケープが必要。
    - `seq 20 | xargs -n8 | parallel -C" " ' for i in {}; do echo $i ; done | tr "\n" " "' `とすると、もっと単純。
         - シングルクォート`'`の間に改行文字を含めてよく、簡単に複数行のコマンド文を埋め込むことが出来る。
 

# Parallelに関して(引用に関する表示)

```
bash-3.2$ parallel --citation
Academic tradition requires you to cite works you base your article on.
If you use programs that use GNU Parallel to process data for an article in a
scientific publication, please cite:

@software{tange_2021_5593566,
      author       = {Tange, Ole},
      title        = {GNU Parallel 20211022 ('Sinclair')},
      month        = Oct,
      year         = 2021,
      note         = {{GNU Parallel is a general parallelizer to run
                       multiple serial command line programs in parallel
                       without changing them.}},
      publisher    = {Zenodo},
      doi          = {10.5281/zenodo.5593566},
      url          = {https://doi.org/10.5281/zenodo.5593566}
}

(Feel free to use \nocite{tange_2021_5593566})

This helps funding further development; AND IT WON'T COST YOU A CENT.
If you pay 10000 EUR you should feel free to use GNU Parallel without citing.

More about funding GNU Parallel and the citation notice:
https://lists.gnu.org/archive/html/parallel/2013-11/msg00006.html
https://www.gnu.org/software/parallel/parallel_design.html#Citation-notice
https://git.savannah.gnu.org/cgit/parallel.git/tree/doc/citation-notice-faq.txt

If you send a copy of your published article to tange@gnu.org, it will be
mentioned in the release notes of next version of GNU Parallel.
```