ファイル名に空白が入っている場合のファイル処理

こういう感じのことである。
[bash] スペースが入ったファイル名の処理 - Qiita


例えばhoge という作業ディレクトリのpdf ファイルをpdftk を使ってひとつのファイルにまとめたいとする。
ファイル名にはなぜか空白文字が含まれているとする。どうしてそんなファイル名にしたんだ…という批判はここではおいておく。
ファイル名はhoge 1.pdfhoge 2.pdfhoge 9.pdfhoge 10.pdfというものがあるとする。ファイル名自体はなんでもいいが、辞書式に並べて1, 10, 2, 3, 4,... となっているものとする。

f=/hoge/

対象のディレクトリに移動してワイルドカード* を指定すれば終了である。

pdftk *.pdf cat output hoge.pdf

と思ったら、これはlsコマンドで辞書式にファイルが並ぶので1, 2, 9, 10 の順ではなく、1, 10, 2, 9 の順でファイルが結合されている。
ではファイルを数字順に並ぶようにコマンドを使うと

pdftk $(ls -v) cat output hoge.pdf
Error: Unable to find file.
Error: Failed to open PDF file:
   hoge
Error: Unable to find file.
Error: Failed to open PDF file:
   1.pdf
Error: Unable to find file.
Error: Failed to open PDF file:
   hoge
Error: Unable to find file.
Error: Failed to open PDF file:
   2.pdf
Error: Unable to find file.
Error: Failed to open PDF file:
   hoge
Error: Unable to find file.
Error: Failed to open PDF file:
   9.pdf
Error: Unable to find file.
Error: Failed to open PDF file:
   hoge
Error: Unable to find file.
Error: Failed to open PDF file:
   10.pdf
Errors encountered.  No output created.
Done.  Input errors, so no output created.

となり、ファイル名の空白文字で分割されるのでうまくいかない。これはこういう仕様のようである。
引数を地道にクオーテーションでくくって入力すると、動く。

pdftk "hoge 1.pdf" "hoge 2.pdf" "hoge 9.pdf" "hoge 10.pdf" cat output hoge.pdf

というわけでファイル名を全部クオーテーションでくくってみる。とある上位のディレクトリから個々の作業ディレクトリ内のファイルを順次変換する、みたいなスクリプトにしたいのでfindでフルパスを取得する。findはファイル表示順がアクセスとか最終変更履歴順らしいのでsortを使って数字順に並べる。
並べたあとはawkで文字列処理を行い、ダブルでもシングルでもクオーテーションでファイル名を挟み込む。

find "$f" -type f | sort -V | awk '{print "\"" $0 "\""}'
"/hoge/hoge 1.pdf"
"/hoge/hoge 2.pdf"
"/hoge/hoge 9.pdf"
"/hoge/hoge 10.pdf"
pdftk $(find "$f" -type f | sort -V | awk '{print "\"" $0 "\""}') cat output hoge.pdf

???

Error: Unable to find file.
Error: Failed to open PDF file:
   "/hoge/hoge
Error: Unable to find file.
Error: Failed to open PDF file:
   1.pdf"
Error: Unable to find file.
Error: Failed to open PDF file:
   "/hoge/hoge
Error: Unable to find file.
Error: Failed to open PDF file:
   2.pdf"
Error: Unable to find file.
Error: Failed to open PDF file:
   "/hoge/hoge
Error: Unable to find file.
Error: Failed to open PDF file:
   9.pdf"
Error: Unable to find file.
Error: Failed to open PDF file:
   "/hoge/hoge
Error: Unable to find file.
Error: Failed to open PDF file:
   10.pdf"
Errors encountered.  No output created.
Done.  Input errors, so no output created.

というわけでこれも出来ないので、クオーテーションでくくったファイルを引数に全部入力するスタイルを無理やり作る。これはevalを使うと出来る。

find "$f" -type f | sort -V | awk '{print "\"" $0 "\""}' | tr "\n" " "

こうすると1行で引数をひたすら並べたようにできる。

"/hoge/hoge 1.pdf" "/hoge/hoge 2.pdf" "/hoge/hoge 9.pdf" "/hoge/hoge 10.pdf"

あとはこれを無理やり文字列にして、evalで実行する。

eval "pdftk $(find "$f" -type f | sort -V | awk '{print "\"" $0 "\""}' | tr "\n" " ") cat output hoge.pdf"