From: Daniel Berger Date: 2007-03-10T05:40:07+09:00 Subject: Re: Getting to the last file in a chain of symlinks On Mar 9, 12:10 pm, "Daniel Berger" wrote: > Hi all, > > Here's a little code snippet I thought I'd share. It follows a chain > of symlinks until you get down to the "real" file. Anyone got a better > approach? > > # On Solaris 10, Sunblade 150 > # > # /dev/fd0 -> fd0c > # /dev/fd0c -> diskette0 > # /dev/diskett0 -> ../devices/pci@1f,0/isa@7/dma@0,0/floppy@0,3f0:c > # > > file = '/dev/fd0' > > while true > Dir.chdir(File.dirname(file)) > file = File.expand_path(File.readlink(file)) > break unless File.symlink?(file) > end > > puts file # /devices/pci@1f,0/isa@7/dma@0,0/floppy@0,3f0:c Alright, here's a modified File.readlink method. This is an improved version of the algorithm above in that it uses the block form of Dir.chdir and handles circular symlinks: class File class << self private alias readlink_orig readlink public # Returns the given symbolic link as a string. If +recursive+ is set # to true then it will follow symbolic links until it gets to the final # file in the chain. The default is false, i.e. non-recursive. # # If circular symlinks are encountered, it will return the last link # that it has not already encountered. # def readlink(file, recursive=false) if recursive visited = {} # Used to avoid circular references while true Dir.chdir(File.dirname(file)){ file = File.expand_path(File.readlink(file)) } if File.symlink?(file) || visited[file] break end visited[file] = true end file else readlink_orig(file) end end end end