cut: illegal option -- -

MacWindows Phone7.5のIS12Tで撮った写真や動画を振り分けるのに書いたワンライナをシェルスクリプトにまとめていたところ、上記のエラーが出ました。

IS12Tが吐く動画はmp4形式で、ファイル名に撮影日時が入ってます。ファイル名は WP_YYYYMMDD_HHmmssZ.mp4の形式で、たとえば WP_20111107_025823Z.mp4 といったものになります。時刻はUTCGMT)になっているので、9時間足すとJSTになります。

で、この時間を切り出すのに:

DATESTR=`echo $FILENAME | cut --output-delimiter=' ' -c4-11,13-14,15-16,17-18 | awk '{DATE=$1; HOUR=$2 ; MIN=$3 ; SEC=$4; HOUR=HOUUR+9 if (HOUR>=24) { HOUR=HOUR-24 ; DATE=DATE+1 } ; printf("%8d%02d%02d.%02d\n", DATE, HOUR, MIN, SEC)}'`

と書いてました。これはWP_20111107_025823Z.mp4という文字列から年月日時分秒を切り出し、9時間足して、また繋げ直した文字列をDATESTRに入れてます。201111071158.23という形式は、touch -tにそのまま食わせてファイルのタイムスタンプを変更できるものです。

こいつをスクリプトに入れてを実行してみるとエラーが出ます。コマンドラインで試していた時はうまく動いてたのに、スクリプトに仕立てたらごちゃごちゃエラーが出る。しばらくいろいろ試行錯誤したすえ、ようやくこのエラーが原因だとわかりました。検索で引っかかるようにちゃんと書いておきます:

cut: illegal option -- -
usage: cut -b list [-n] [file ...]
       cut -c list [file ...]
       cut -f list [-s] [-d delim] [file ...]

これは何が起きているかというと、cut --output-delimiter=' ' -c4-11,13-14,15-16,17-18と書いたうちの、--output-delimiterオプションをcutコマンドが食ってくれてない、ということ。

原因は、コマンドライン環境が後入れのGNUのコマンドを優先するように設定してあり /opt/local/libexec/gnubin/cut を使うのに対し、スクリプトの実行環境では /usr/bin/cut にあるBSDのコマンドを使ってしまうためでした。案外わかりにくかったです。

修正はどうしましょう。BSDのcutでも-dでデリミタを設定できるようですが、これはたとえばスクリプトLinux環境に持っていった時に、同じごちゃごちゃのエラーで悩むことになります。どっちにも対応するように環境をテストして…なんてことをシェルスクリプトでやる気はありません。エラーとその原因を一致させれば十分でしょう。

簡単な修正でこれをするには、gnuツールをいつも使い、無ければCommand not foundが出るように、cutをgcutと書くことだと思います。

DATESTR=`echo $FILENAME | gcut --output-delimiter=' ' -c4-11,13-14,15-16,17-18 | gawk '{DATE=$1; HOUR=$2 ; MIN=$3 ; SEC=$4; HOUR=HOUUR+9 if (HOUR>=24) { HOUR=HOUR-24 ; DATE=DATE+1 } ; printf("%8d%02d%02d.%02d\n", DATE, HOUR, MIN, SEC)}'`

他の設計選択があるような気もするけど、これが今のところベストプラクティスだと感じています。