Perl 的 file handle 及 directory handle 一定是 global 的,無法宣告成 local
一般使用上沒有大問題,但是當用在遞迴式呼叫時,就會產生錯誤了,下面是一個把目錄下包含子目錄中所有檔案列出來的 perl 程式,採用遞迴式呼叫。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #!/usr/bin/perl die "Usage: $0 [directory]\n" unless @ARGV == 1; die "ERROR: $ARGV[0] is not a directory\n" unless -d $ARGV[0]; &show_dir($ARGV[0]); exit; sub show_dir { my( $dir ) = @_; my( $fname ); opendir( DIR, $dir ); while( $fname = readdir(DIR) ) { next if $fname eq '.' || $fname eq '..'; if( -d "$dir/$fname" ) { &show_dir("$dir/$fname"); } else { print "$dir/$fname\n"; } } closedir(DIR); } |
由於 DIR 這個 directory-handle 會被當成 global 變數,因此這段程式會出錯,無法列出所有檔案。
解決方法是把 DIR 這一個 directory-handle 直接用 $dir 來代替,這樣在遞迴的時候就不會因為重複使用而造成錯誤了,下面是改過的程式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #!/usr/bin/perl die "Usage: $0 [directory]\n" unless @ARGV == 1; die "ERROR: $ARGV[0] is not a directory\n" unless -d $ARGV[0]; &show_dir($ARGV[0]); exit; sub show_dir { my( $dir ) = @_; my( $fname ); opendir( $dir, $dir ); while( $fname = readdir($dir) ) { next if $fname eq '.' || $fname eq '..'; if( -d "$dir/$fname" ) { &show_dir("$dir/$fname"); } else { print "$dir/$fname\n"; } } closedir($dir); } |