この人頭いいなと思ったエピソード

こんにちは。
シェルスクリプトで謎の現象が起こりまして悩んでいます。

現在、
#!/usr/bin/sh
var='foo'
if [ $? - eq - 0 ]; then
mv xxx.bz2 xxx.old.bz2
echo $var | bzip2 -z >xxx.bz2
fi
といった感じのシェルスクリプトを動かしています。
これを手作業で、
foo | bzip2 -z >xxx.tmp.bz2
とやると、xxx.tmp.bz2は1.2MB程度のファイルとなるのですが、
上記のシェルスクリプトで実行すると8KBほどにしかなりません。

シェルスクリプトの変数のサイズの制限かと思い、調べてみましたが、
特に制限があるとの資料はみつかりませんでした。
fooの出力がバイナリなので、そのせいかとも思ったのですが、unix系列の場合、windowsと違ってテキスト/バイナリの区別はないはずだしということで、理由がわかりません。

シェルの変数には、やはり制限があるのでしょうか?それとも他の理由でしょうか。ご存知の方がいらっしゃいましたら、ご教示お願いします。

環境はsolarisです。バージョンは、
$ cat /etc/release
Solaris 10 8/07 s10s_u4wos_12b SPARC
Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
Use is subject to license terms.
Assembled 16 August 2007

です。よろしくお願いします。

A 回答 (4件)

変数と言うより、シェルのコマンドライン長の制約の気がします。


圧縮して1.2MBということはfooの出力は数十~数百MB?
外部コマンド起動の場合は、Linuxだと128KBが上限のようですが、echoは組み込みコマンドなので、もっと上限は大きいはずです。
変数に200MBいれてみると、入りましたけど、echoしてみるとbashが落ちました。SolarisだとOSが違うので、上限も異なると思いますが。

やはり変数に入れない方がいいでしょうね。

foo | bzip2 -z >xxx.tmp.bz2
ただ、ステータスを調べるのは面倒。パイプのステータスはパイプの最終段のコマンドつまりbzip2のステータスになります。

bashだと、${PIPESTATUS[0]} でfooのステータスが取れるのですが、shだとちょっと細工が要ります。

status=`((foo ; echo $? >&3) | bzip2 -z >xxx.tmp.bz2) 3>&1`
if [ $status = 0 ]
then mv xxx.bz2 xxx.old.bz2; mv xxx.tmp.bz2 xxx.bz2
else rm xxx.tmp.bz2
fi

この回答への補足

うまくいきました。ありがとうございます。

補足日時:2009/05/15 14:07
    • good
    • 0
この回答へのお礼

なるほど、ありがとうございます。
どうやら変数に入れないほうがいいのは確かなようですね。

>ただ、ステータスを調べるのは面倒。パイプのステータスはパイプの最終段のコマンドつまりbzip2のステータスになります。
はい、ステータスを調べる必要があるので・・。必要なければ素直に
foo | bzip2 -z >xxx.tmp.bz2
で、よかったのですが。
>status=`((foo ; echo $? >&3) | bzip2 -z >xxx.tmp.bz2) 3>&1`
>if [ $status = 0 ]
>then mv xxx.bz2 xxx.old.bz2; mv xxx.tmp.bz2 xxx.bz2
>else rm xxx.tmp.bz2
>fi
参考になります。試してみます。

お礼日時:2009/05/15 10:08

んー。

fooの出力結果をbz2で保存したいというのが目的でよいのかな?

Solaris は、時々コマンドが微妙に違っていたりするのであまり自信ないですけど
シェルでは、基本的にクォーティングする癖をつけた方がよいですよ。

#!/usr/bin/sh
var="$(foo)"
if [ $? -eq 0 ]; then
mv xxx.bz2 xxx.old.bz2
echo "$var" | bzip2 -zc >xxx.bz2 || echo error
fi

としてみたら、どんなです?
もしうまくいったとしたら、$varに0x0dが混ざっていたのでしょう。
    • good
    • 0
この回答へのお礼

お返事ありがとうございます。
テストコードを書いてみました。
$ cat test.sh
#!/usr/bin/sh
var0="\0015"
var=12345${var0}A
echo $var
echo "$var"

$ test.sh
A2345
A2345

と、なりましたので、どうやら改行が原因ではないようです。
他、
var0="\0042"
としても試してみましたが、結果、
12345"A
12345"A
と、なりましたので、バイナリであることはおそらく問題がないのかなと思います。
いずれにせよ、あまり大きなデータを変数に入れるのは問題があるようなので、変数に入れない方向で考えてみます。

お礼日時:2009/05/15 11:19

echo は文字列しか処理できないんじゃない?


シェルにも
echo $var | bzip2 -z >xxx.bz2
じゃなくて
foo | bzip2 -z >xxx.tmp.bz2
って書けばどう?
    • good
    • 1

この場合


echo $var = echo foo
だから, 「コマンド foo の出力を bzip2 で圧縮する」んじゃなくて「文字列 foo を bzip2 で圧縮してる」んだよ.

この回答への補足

すみません、間違えました。
var='foo'
じゃなくて、
var=`foo`
でした。申し訳ないです。

補足日時:2009/05/14 19:10
    • good
    • 0
この回答へのお礼

重ねてすみません。
間違えたというのは、転記ミスということです。
うまく動かないスクリプトに書いてあるのは、
var=`foo`
です。

お礼日時:2009/05/14 19:15

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報