はじめに
プログラムかなんかでファイルの一覧を取得したいなーってときありますよね。
一覧だじゃなくて階層ごと取りたいってこともあるとかないとか。
そこでファイルの一覧を取得できるperlの「glob」を使ってみます
参考はこちらhttp://d.hatena.ne.jp/perlcodesample/20080529/1212075850
構文は以下
my $path = "/hoge/hoge/hoge/*"; # 一覧を取得したいディレクトリのパス my @files_list = glob "$path"; もしくは my @files_list = <$path>;
いきなりの補足ですが<>でglobと同じらしいです。
ダイアモンド演算子と同じ?っていうのはglobがよくわかってないのでわかりませんw
さっそくプログラムを書いてテスト
試すディレクトリの中は適当にファイルとディレクトリを作ってみました。こんな感じ
# tree glob_test_dir glob_test_dir |-- a.file |-- a.txt |-- any_dir_01 | |-- aaaa.txt | `-- bbbb.txt |-- any_dir_02 |-- any_file |-- b.file |-- b.txt |-- c.txt |-- test01.text |-- test02.text `-- test03.text
プログラムはglob_test_dirがいるところと同ディレクトリに作るとします
すべて取得してみる
glob_all.pl
my $path = "./glob_test_dir/*"; my @files = glob $path; warn Dumper @files;
結果
# perl glob_all.pl
$VAR1 = './glob_test_dir/a.file';
$VAR2 = './glob_test_dir/a.txt';
$VAR3 = './glob_test_dir/any_dir_01';
$VAR4 = './glob_test_dir/any_dir_02';
$VAR5 = './glob_test_dir/any_file';
$VAR6 = './glob_test_dir/b.file';
$VAR7 = './glob_test_dir/b.txt';
$VAR8 = './glob_test_dir/c.txt';
$VAR9 = './glob_test_dir/test01.text';
$VAR10 = './glob_test_dir/test02.text';
$VAR11 = './glob_test_dir/test03.text';
フォルダも一覧の中に含まれてます
aではじまるファイルだけ取得、.textだけ取得とかやってみる
glob_specific.pl
# aではじまるやつ my $path = "./glob_test_dir/a*"; my @files = glob $path; warn Dumper @files; # .textで終わるやつ my $path = "./glob_test_dir/*.text"; my @files = glob $path; warn Dumper @files;
結果
# perl glob_specific.pl
$VAR1 = './glob_test_dir/a.file';
$VAR2 = './glob_test_dir/a.txt';
$VAR3 = './glob_test_dir/any_dir_01';
$VAR4 = './glob_test_dir/any_dir_02';
$VAR5 = './glob_test_dir/any_file';$VAR1 = './glob_test_dir/test01.text';
$VAR2 = './glob_test_dir/test02.text';
$VAR3 = './glob_test_dir/test03.text';
<>を使ってみる
glob_kigou.l
# これはダメらしい ※理由は特に調べてません my $path = "./glob_test_dir/*"; my @files = <$path>; warn Dumper @files; # こっちはOK my $path = "glob_test_dir/*"; my @files = <./$path>; warn Dumper @files;
結果
# perl glob_kigou.pl
readline() on unopened filehandle at glob_kigou.pl line 8.
Warning: something's wrong at glob_kigou.pl line 9.$VAR1 = './glob_test_dir/a.file';
$VAR2 = './glob_test_dir/a.txt';
$VAR3 = './glob_test_dir/any_dir_01';
$VAR4 = './glob_test_dir/any_dir_02';
$VAR5 = './glob_test_dir/any_file';
$VAR6 = './glob_test_dir/b.file';
$VAR7 = './glob_test_dir/b.txt';
$VAR8 = './glob_test_dir/c.txt';
$VAR9 = './glob_test_dir/test01.text';
$VAR10 = './glob_test_dir/test02.text';
$VAR11 = './glob_test_dir/test03.text';
※全体的にshebangやuse strictとかは省いて書いてます。
glob使ってツリー構造を自分で作ってみる
globでファイルの一覧が取得できましたがディレクトリも含まれるので自前で判定します。
判定して除外だけとか面白くないのでツリー構造をperlの変数で作ってみました
glob_tree.pl
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my $arg = $ARGV[0]; my $scan_dir_path = ($arg) ? $arg :'.'; my $tree; $tree = &scan_dir($scan_dir_path); # 下位階層のディレクトリもすべてglobで捜査して$tree変数に格納 sub scan_dir { my $scan_dir_path = shift; # 念のため後方スラッシュ削除&"/*"を付けたし $scan_dir_path =~ s/\/$//; $scan_dir_path = $scan_dir_path . "/*"; my $tree = []; my @pathes = glob $scan_dir_path; foreach my $path (@pathes) { if( -d $path ) { # pathがディレクトリの場合は再帰 my $tmp_tree = {}; $tmp_tree->{$path} = &scan_dir($path); push @$tree, $tmp_tree; } else { push @$tree, $path; } } return $tree; } warn Dumper $tree; 1;
結果
perl list_dir_and_file.pl "./glob_test_dir/" $VAR1 = [ './glob_test_dir/a.file', './glob_test_dir/a.txt', { './glob_test_dir/any_dir_01' => [ './glob_test_dir/any_dir_01/aaaa.txt', './glob_test_dir/any_dir_01/bbbb.txt' ] }, { './glob_test_dir/any_dir_02' => [] }, './glob_test_dir/any_file', './glob_test_dir/b.file', './glob_test_dir/b.txt', './glob_test_dir/c.txt', './glob_test_dir/test01.text', './glob_test_dir/test02.text', './glob_test_dir/test03.text' ];
tips
globは危険という記事も見つけたので合わせてのせておきます
外部入力とかありそーなら気をつけましょうという感じでしょうか。
→Perl の危険な関数