それ use open

しかし、

test.pl < utf8.txt

は行けるが、

test.pl utf8.txt

はだめ。

にも書いたけど、引数を指定した場合、<> は STDIN じゃないですから当然ですね。とりあえず

use open IN => ':utf8';

とするほうが、スマートといえばスマートか?
や、Encode::decode を使うのが駄目ってことはないと思うけど。

追記

dankogai さんから Trackback が飛んできて気づいたのだが、書き方が分かりにくいな。ここでは、

use strict;
use warnings;
use utf8;
use open IN => ':utf8';
binmode STDOUT, ':utf8';
while (<>) {
    print if /[ぁ-ん]/;
}

とするのではなくて、山下さんの元のプログラムに対して use open を追加するとい意味。つまり

use strict;
use warnings;
use utf8;
use open IN => ':utf8';
binmode STDIN, ':utf8';
binmode STDOUT, ':utf8';
while (<>) {
    print if /[ぁ-ん]/;
}

ということ。詳細は Trackback 元を参照。