lsコマンドをPerlで
「ls」コマンドをPerlで実装してみた。
端末の画面幅の取得の仕方がわからなかった。
なのでとりあえずファイル名出力列は4行固定。
汚染チェックもいるのか不明。
#!/usr/bin/perl -T # ls.pl # "ls"コマンドをPerlで実装 use strict; use warnings; use List::Util qw(max); require Carp; my $readkey_ok = eval { local $SIG{__DIE__}; local $SIG{__WARN__}; require Term::Readkey; # 端末画面幅を取得したい }; # 表示ディレクトリ my $dir = shift || './'; # 引数が指定されていなければカレントをデフォルトにする # untainted $dir =~ s/^(\w+)$/$1/; # ディレクトリ内ファイル取得 opendir my $dh, $dir or Carp::croak("ls.pl: $dir: No Such file or directory"); my @files = map { {name => $_.q{ }, len => length($_)} } sort grep { !/^\./ } # 不可視ファイルを無視 readdir $dh; closedir $dh; # ファイル名最大長 my $maxlen_fname = max(@{[map($_->{len}, @files)]}); # ファイル数 my $count_file = @files; # もしファイルがあれば if ($count_file) { my $cols = 4; # 列数 my $rows = ($count_file % $cols) # 行数 ? int($count_file / $cols + 1) : int($count_file / $cols); my @print_arrays = ('dummy'); while (@files) { my @arr = ('dummy'); push @arr, shift(@files) for 1 .. $rows; for my $i (1 .. $rows) { my $suff = ($i % $rows) ? ($i % $rows) : $rows; if ($arr[$i]) { # そこに出力ファイルがあれば if (my $diff_len = $maxlen_fname - $arr[$i]->{len}) { $arr[$i]->{name} = $arr[$i]->{name}.(q{ } x $diff_len); } push @{$print_arrays[$suff]}, $arr[$i]->{name}; } } } shift @print_arrays; for my $print_col (@print_arrays) { print "@$print_col\n"; } } __END__