พิมพ์ directory

  • warning: realpath() [function.realpath]: SAFE MODE Restriction in effect. The script whose uid is 1005 is not allowed to access /tmp owned by uid 0 in /var/www/sites/sugree/codenone.com/subdomains/www/html/includes/file.inc on line 190.
  • warning: realpath() [function.realpath]: SAFE MODE Restriction in effect. The script whose uid is 1005 is not allowed to access /tmp owned by uid 0 in /var/www/sites/sugree/codenone.com/subdomains/www/html/includes/file.inc on line 190.

โจทย์

def tlist(root,prefix='',symbol='',suffix='',deep=0)
 
  puts prefix + symbol + suffix + (deep == 0 ? root : File.basename(root))
 
  if File.directory?(root) 
    entries = Dir.entries(root).sort
    entries.each_with_index do |ent, i|
      nsymbol = i == entries.size - 1 ? '`' : '|'
      nprefix = (symbol == '`' ? "   " : "!  ") * deep
      unless ent =~ /^\.|\.\.$/
        tlist(File.expand_path(ent, root), nprefix, nsymbol, '--', deep+1)
      end
    end
  end
end

พยายามใช้ตัวแปรชื่อเดียวกับคุณสุกรี
จะได้นำไปเปรียบเทียบกับ python ได้ง่าย

ส่วนที่ต่างกัน และน่าหงุดหงิดนิดหน่อยสำหรับผมก็คือ
ลำดับของ argument ใน File.expand_path(ent, root)
ซึ่งเทียบเท่ากับ os.path.join(root,ent) ใน python
คือลำดับของ python ดูเป็นธรรมชาติกว่า
ซึ่ง่ประเด็นของลำดับแบบนี้อาจจะเป็นเพราะ คนญี่ปุ่นเป็นคนเขียน
เลยทำให้ลำดับสลับในลักษณะขวามาซ้ายก็ได้

ส่วนที่ต่างกันอีกจุด ก็คือ ใน python
array ที่ return จาก os.listdir(root)
จะไม่มี "." กับ ".."
แต่ของ ruby Dir.entries(root) จะรวม "." กับ ".." มาด้วย

ส่วน code ข้างล่างนี้ ลองทำ variation ไปอีกแบบ

def tlist2(root,prefix='',symbol='',suffix='',deep=0)
 
  puts prefix + symbol + suffix + (deep == 0 ? root : File.basename(root))
 
  if File.directory?(root) 
 
    entries = Dir.entries(root).delete_if {|x| x=~ /^\.(\.)?$/}.sort
    symbols = ['|'] * (entries.size - 1) << '`'
    nprefix = (symbol == '`' ? "   " : "!  ") * deep
 
    entries.zip(symbols.to_a) do |ents|
        tlist2(File.expand_path(ents[0], root), nprefix, ents[1], '--', deep+1)
    end
 
  end
end

Note: ตัวแปร argument suffix สามารถเอาออกได้
แต่ขี้เกียจแล้ว

ขุดโจทย์ล้านปีเอามาเล่นว่างๆ หลังเกม Champions League
ตรง directory ขอเป็นสัญลักษณ์'+' ละกัน รู้สึกจะชัดเจนกว่า
เขียนไปเขียนมาเกือบไม่ขำ... ได้ออกมาหน้าตาแบบนี้

class Tree
  Node = Struct.new(:parent,:files,:child)
  def initialize(path)
      @tree = Tree.create_tree(path)
  end
  def ls
      Tree.print_tree(@tree)
  end
  def self.create_tree(path)
      node = Node.new(path,[],[])
      Dir["#{path}/*"].each do |item|
	node.files << item.gsub("#{path}/","") if File.file? item
	node.child << create_tree(item) if File.directory? item 
      end
      node
  end
  def self.print_tree(tree,deep=0)
    if deep == 0 then
	puts "+#{tree.parent}"
	files = tree.files
	files.each {|f| puts files[files.size-1]== f ? "  `-- #{f}" : "  |-- #{f}" } 
    end
    unless tree.size == 0 
	space = ""
	0.upto(deep){ space << "|  "}
	tree.child.each do |new_node|
	puts "  #{space}+#{new_node.parent.split("/")[-1]}"
	files = new_node.files
	files.each{|f| puts files[files.size-1]== f ? "  #{space}`-- #{f}" : "  #{space}|-- #{f}"}
	print_tree(new_node,deep+1)
	end
    end
  end
end
t = Tree.new("/path/to/dir")
t.ls

ป.ล. หวังว่าสักวันจะเขียนสั้นๆได้แบบข้างบนบ้าง :P
ป.ล.2 ขอบคุณ p'pok ครับ แก้ใหม่แล้ว (ทำไมไม่เขียนแบบนี้ตั้งแต่แรก งงตัวเอง)

... if File.file? File.join(path,file)} if File.directory? path

ตรงนี้อ่านยาก

Dir.entries(path).each{|file| node.files << file if File.file? File.join(path,file)} if File.directory? path
Dir["#{path}/*"].each{|dir| node.child << create_tree(dir)  if File.directory? dir }

อันนี้น่าจะยุบรวมกันได้ (โปรแกรมเมอร์หัวเก่า มันจะไปนึกถึงเรื่องการวบลูปเกินจำเป็น)

sugree's picture

ถึงขั้นมึนจนอ่านไล่ไม่ทัน

ย้าย Codenone

ประกาศย้าย Codenone ไปใช้ Forum ของ Blognone แทนครับ ตามไปตั้งกระทู้ต่อได้ที่ Codenone Forum (รายละเอียดอ่านจากกระทู้ ย้าย Codenone ไปรวมกับ Blognone)

กระทู้เก่าๆ จะย้ายตามไปในภายหลัง ตอนนี้ปิดการโพสต์กระทู้ไว้ เหลือไว้เฉพาะอ้างอิงเท่านั้น