そんな場合に利用可能な言語で自前のツールとして用意しておくと助かる場合もある。以下は、シンボリックリンクや日本語のソート(sjisコード順)には対応せず、単純なソートと再帰呼び出しの組み合わせである。
1.perl で tree コマンド作成
#! /usr/bin/perl use utf8; #use Encode qw/encode decode/; use Encode; if (scalar(@ARGV) == 0) { $root_dir = "." } else { $root_dir = shift(@ARGV); } printf("%s\n",$root_dir); &tree("",$root_dir); sub tree { my($depth,$dir) = @_; if (!opendir(FD,$dir)) { printf("Can't open dir[%s]\n",$dir); exit(1); } my(@list) = (); foreach $file (readdir(FD)) { if ($file =~ /^[.]$/ || $file =~ /^[.][.]$/) { next; } # $file = decode('UTF-8', $file); # $file = encode('Shift_JIS', $file); push(@list,$file) } close(fd); my($cnt) = 0; foreach $file (sort @list) { $cnt++; # $file = decode('Shift_JIS', $file); # $file = encode('UTF-8', $file); my($fullpath) = $dir . "/" . $file; if ( -d $fullpath ) { if (scalar(@list) == $cnt) { printf("%s`-- %s\n",$depth,$file); tree($depth . " ",$fullpath); } else { printf("%s|-- %s\n",$depth,$file); tree($depth . "| ",$fullpath); } } else { if (scalar(@list) == $cnt) { printf("%s`-- %s\n",$depth,$file); } else { printf("%s|-- %s\n",$depth,$file); } } } }
2.ruby で tree コマンド作成
#! /usr/bin/ruby def tree(depth,dir) f = Dir.open(dir); list = [] f.each{ |file| if (file =~ /^[.]$/ || file =~ /^[.][.]$/) next end # file = file.encode("Shift_JIS", :undef => :replace, :replace => "*") list.push(file) } cnt = 0 list.sort.each {|file| # file = file.encode("UTF-8") cnt = cnt +1 fullpath = dir + "/" + file if (File.ftype(fullpath) == "directory") if (list.length == cnt) printf("%s`-- %s\n",depth,file) tree(depth + " ",fullpath) else printf("%s|-- %s\n",depth,file) tree(depth + "| ",fullpath) end else if (list.length == cnt) printf("%s`-- %s\n",depth,file) else printf("%s|-- %s\n",depth,file) end end } end if (ARGV.size() == 0) root_dir = "." else root_dir = ARGV[0] end printf("%s\n",root_dir) tree("",root_dir)
3.python で tree コマンド作成
#! /usr/bin/python import os import sys def tree(depth,dir): files = sorted(os.listdir(dir)) cnt = 0 for file in files: fullpath = dir + "/" + file cnt = cnt + 1 if os.path.isdir(fullpath): if len(files) == cnt: print "%s`-- %s"%(depth,file) tree(depth + " " ,fullpath) else: print "%s|-- %s"%(depth,file) tree(depth + "| " ,fullpath) else: if len(files) == cnt: print "%s`-- %s"%(depth,file) else: print "%s|-- %s"%(depth,file) root_dir = "." if len(sys.argv) > 1: root_dir = sys.argv[1] print root_dir tree("",root_dir)
4.clisp で tree コマンド作成
#! /usr/bin/clisp (defun fname-chop(tfile) ;; (let ((buf (namestring tfile))) (setq ch (subseq buf (- (length buf) 1) (length buf))) (if (equal ch "/") (subseq buf 0 (- (length buf) 1)) (subseq buf 0 (length buf))))) (defun tree(depth dir) (let ( (list (concatenate 'list (directory (concatenate 'String dir "*/")) (directory (concatenate 'String dir "*")))) (tmp "") (cnt 0)) (sort list #'string< :key #'fname-chop) (dolist (file list) (progn (incf cnt) (setq tfile (namestring file)) (setq tfile (subseq tfile 0 (- (length tfile) 1))) (if (equal (file-namestring file) "") (if (equal (length list) cnt) (progn (format t "~A`-- ~A~%" depth (file-namestring tfile)) (tree (concatenate 'String depth " ") (namestring file)) ) (progn (format t "~A|-- ~A~%" depth (file-namestring tfile)) (tree (concatenate 'String depth "| ") (namestring file)) )) (if (equal (length list) cnt) (progn (format t "~A`-- ~A~%" depth (file-namestring file)) ) (progn (format t "~A|-- ~A~%" depth (file-namestring file)) ))))))) (let ((root_dir "")) (if (equal (length *args*) 0) (setq root_dir "./") (setq root_dir (car *args*))) (if (not (equal (subseq root_dir (- (length root_dir) 1) (length root_dir)) "/")) (format t "test01 [dir]")) (format t "~A~%" root_dir) (tree "" root_dir))
5.java で tree コマンド作成
import java.io.*; import java.util.*; class tree { void tree(String depth,File dir) { File[] files = dir.listFiles(); int cnt = 0; Arrays.sort(files); if (files == null) { return; } for(File file: files) { cnt++; if (file.isDirectory()) { if (files.length == cnt) { System.out.printf("%s`-- %s\n",depth,file.getName()); tree(depth + " ",new File(file.getAbsolutePath())); } else { System.out.printf("%s|-- %s\n",depth,file.getName()); tree(depth + "| ",new File(file.getAbsolutePath())); } } else { if (files.length == cnt) { System.out.printf("%s`-- %s\n",depth,file.getName()); } else { System.out.printf("%s|-- %s\n",depth,file.getName()); } } } } public static void main(String args[]) { String root_dir = "."; if (args.length != 0) { root_dir = args[0]; } System.out.printf("%s\n",root_dir); tree obj = new tree(); obj.tree("",new File(root_dir)); } }
6.C言語 で tree コマンド作成
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #include <string.h> #include <unistd.h> typedef struct dirent DENT; typedef struct { int cnt; DENT *list; } DENT_B; int comp(src,dst) DENT *src; DENT *dst; { return(strcmp(src->d_name,dst->d_name)); } int list_alloc(base) DENT_B *base; { if (!base->list) { base->list = malloc(sizeof(DENT)*base->cnt); if (!base->list) { return(1); } } else { base->list = realloc(base->list, sizeof(DENT)*base->cnt); } return(0); } int mklist(base,dir) DENT_B *base; char *dir; { DIR *dp = NULL; int cnt = 0; DENT *dent = NULL; dp=opendir(dir); if (!dp) { fprintf(stderr,"Can't open directory(%s)\n",dir); return(1); } base->cnt = 0; while(dent = readdir(dp)) { if (dent == (struct dirent *)-1) { fprintf(stderr,"Can't read directory(%s)\n",dir); return(1); } if (!strcmp(dent->d_name,".") || !strcmp(dent->d_name,"..")) { continue; } base->cnt++; if (list_alloc(base)) { fprintf(stderr,"Can't alloc memory\n"); return(1); } memcpy(&base->list[base->cnt-1],dent,sizeof(DENT)); } if (closedir(dp)) { fprintf(stderr,"Can't close directory(%s)\n",dir); return(1); } return(0); } int tree(depth, dir) char *depth; char *dir; { DENT_B base; int cnt; char fullpath[512]; char depth_tmp[512]; struct stat dstat; memset(&base,0x00,sizeof(base)); if (mklist(&base,dir)) { fprintf(stderr,"mklist error(%s)\n",dir); return(1); } qsort(base.list,base.cnt,sizeof(DENT),comp); for(cnt=0;cnt<base.cnt;cnt++) { sprintf(fullpath,"%s/%s",dir,base.list[cnt].d_name); if (stat(fullpath,&dstat)) { fprintf(stderr,"stat error(%s)\n",fullpath); return(1); } if (dstat.st_mode & S_IFDIR) { if (cnt+1 == base.cnt) { printf("%s`-- %s\n",depth,base.list[cnt].d_name); sprintf(depth_tmp,"%s ",depth); tree(depth_tmp,fullpath); } else { printf("%s|-- %s\n",depth,base.list[cnt].d_name); sprintf(depth_tmp,"%s| ",depth); tree(depth_tmp,fullpath); } } else { if (cnt+1 == base.cnt) { printf("%s`-- %s\n",depth,base.list[cnt].d_name); } else { printf("%s|-- %s\n",depth,base.list[cnt].d_name); } } } free(base.list); return(0); } int main(argc,argv) int argc; char *argv[]; { char *root_dir = NULL; root_dir = "."; if (argc > 1) { root_dir = argv[1]; } printf("%s\n",root_dir); if (tree("",root_dir)!=0) { exit(1); } exit(0); }
7.速度比較(2455 directories, 22931 files)
== perl == real 0m0.202s user 0m0.112s sys 0m0.088s == ruby == real 0m0.333s user 0m0.196s sys 0m0.112s == python == real 0m0.234s user 0m0.116s sys 0m0.112s == lisp == real 0m2.564s user 0m1.736s sys 0m0.792s == java == real 0m1.050s user 0m1.472s sys 0m0.432s == C == real 0m0.101s user 0m0.020s sys 0m0.080s
0 件のコメント:
コメントを投稿