こういう感じのことである。
[bash] スペースが入ったファイル名の処理 - Qiita
例えばhoge
という作業ディレクトリのpdf ファイルをpdftk
を使ってひとつのファイルにまとめたいとする。
ファイル名にはなぜか空白文字が含まれているとする。どうしてそんなファイル名にしたんだ…という批判はここではおいておく。
ファイル名はhoge 1.pdf
hoge 2.pdf
hoge 9.pdf
hoge 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"