Если вы поместите вызов binmode внутри цикла while, он переключит дескриптор в режим utf8 ПОСЛЕ того, как будет прочитана первая строка. Это, вероятно, не то, что вы хотите сделать.
Что-то вроде следующего может работать лучше:
#!/usr/bin/env perl -w
binmode STDOUT, ':utf8';
eof() ? exit : binmode ARGV, ':utf8';
while( <> ) {
my @chars = split //, $_;
print "$_\n" foreach(@chars);
} continue {
binmode ARGV, ':utf8' if eof && !eof();
}
Вызов eof () с паренами является магическим, так как он проверяет конец файла в дескрипторе псевдо-файла, используемом <>. При необходимости он откроет следующий дескриптор, который должен быть прочитан, что обычно делает * ARGV допустимым, но ничего не читая из него. Это позволяет нам преобразовывать первый файл, с которого производится чтение, до того, как что-либо из него будет прочитано.
Позже, eof (без паренов) используется; это проверяет последний дескриптор, который был прочитан для конца файла. Это будет верно после того, как мы обработаем последнюю строку каждого файла из командной строки (или когда stdin достигнет своего конца).
Очевидно, что если мы только что обработали последнюю строку одного файла, вызов eof () (с паренами) открывает следующий файл (если он есть), делает * ARGV действительным (если это возможно) и проверяет наличие конец файла в этом следующем файле. Если этот следующий файл присутствует и не находится в конце файла, мы можем смело использовать binmode на ARGV.