1
2proc ls {args} {
3    set short 1
4    while {[llength $args] > 0} {
5	set arg [lindex $args 0]
6	switch -glob -- $arg {
7	-*l*	{set short 0}
8	-*	{}
9	default	{break}
10	}
11	set args [lrange $args 1 end]
12    }
13    if {[llength $args] == 0} {set args .}
14
15    set ret {}
16    foreach path $args {
17	catch {vfs::auto $path -readonly}
18	if {![file isdirectory $path]} {
19	    lappend ret [_ls1 $path $short]
20	}
21    }
22    foreach path $args {
23	if {[file isdirectory $path]} {
24	    if {[llength $args] > 1} {
25		if {[llength $ret] > 0} {lappend ret {}}
26		lappend ret "$path:"
27	    }
28	    set list [glob -nocomplain [file join $path *] [file join $path .*]]
29	    foreach file [lsort -dictionary $list] {
30		set tail [file tail $file]
31		if {$tail == "." || $tail == ".."} {continue}
32		lappend ret [_ls1 $file $short]
33	    }
34	}
35    }
36    return [join $ret \n]
37}
38proc _ls1 {path {short 0}} {
39    if {$short} {
40	return [file tail $path]
41    }
42    if {[file type $path] eq "link"} {
43      return [format {%54s %s} "(broken symlink)" [file tail $path]]
44    }
45    file stat $path sb
46    #drwxr-xr-x    3 888      999           21 May 13 19:46 vjscdk
47    return [format {%s %4d %-8s %-8s %7d %s %s} \
48	[fmode sb] $sb(nlink) $sb(uid) $sb(gid) $sb(size) \
49	[clock format $sb(mtime) -format {%b %d %H:%M} -gmt 1] \
50	[file tail $path]]
51}
52
53proc fmode arr { # From Richard Suchenwirth, bag of algorithms, file mode
54    upvar 1 $arr sb
55
56    if {$sb(type) == "directory"} { set pfx "d" } else { set pfx "-" }
57
58    set s [format %03o [expr $sb(mode)%512]]
59    foreach i {  0   1   2   3   4   5   6   7} \
60	    j {--- --x -w- -wx r-- r-x rw- rwx} {
61	regsub -all $i $s $j s
62    }
63    return $pfx$s
64}
65
66if {[catch [concat ls $argv] ret]} {
67    puts stderr $ret
68    exit 1
69}
70
71puts stdout $ret
72