そんな場合に利用可能な言語で自前のツールとして用意しておくと助かる場合もある。以下は、シンボリックリンクや日本語のソート(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 件のコメント:
コメントを投稿