[OT] sh command that ascends dir tree for executable

Before I do and implement this myself, want to make sure it doesn;t
already exist in some fashion: A command line utility like 'sh' but one
that will ascend the directory tree to find the executable.

Thanks,
T.

Yuck. Try this simpler code:

require 'pathname'

class Pathname
def ancestors
   return [self] if self==parent
   return [self] + parent.ancestors
end
end

def find_program_hierarchically(p)
   dir=Pathname.getwd.ancestors.find {|d| (d+p).executable?} + p
end

···

On Sat, 12 Aug 2006 17:43:02 +0000, Jeffrey Schwab wrote:

Trans wrote:

Before I do and implement this myself, want to make sure it doesn;t
already exist in some fashion: A command line utility like 'sh' but one
that will ascend the directory tree to find the executable.

# Caution: On Windows, File.executable? is roughly equivalent to
File.exist?.

def find_program_hierarchically(p)
     d = File.expand_path('.')

     # Remove drive letter for Windows paths.
     d.gsub!(/^[^\/]*/, '')

     while d.length != 0
         f = "#{d}/#{p}"
         return f if File.executable?(f)
         d.gsub!(/\/[^\/]*$/, '')
     end

     return nil
end

puts find_program_hierarchically('main.rb')
puts find_program_hierarchically('nonesuch')
puts find_program_hierarchically('hello.txt')

--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/

Thanks Jeffrey and Ken. I was thinking maybe there was a util for this
already but I suppose not. I wrote code like this:

  Dir.chdir('..') until File.exectuable?( file )

It does change the directory, but for my purposes that's okay. See any
problems with that? Work with Windows okay?

Thanks,
T.

I have a habit of writing really really long one-liners.

--Ken

···

On Sun, 13 Aug 2006 23:01:19 +0000, Jeffrey Schwab wrote:

Ken Bloom wrote:

On Sat, 12 Aug 2006 17:43:02 +0000, Jeffrey Schwab wrote:

Trans wrote:

Before I do and implement this myself, want to make sure it doesn;t
already exist in some fashion: A command line utility like 'sh' but one
that will ascend the directory tree to find the executable.

# Caution: On Windows, File.executable? is roughly equivalent to
File.exist?.

def find_program_hierarchically(p)
     d = File.expand_path('.')

     # Remove drive letter for Windows paths.
     d.gsub!(/^[^\/]*/, '')

     while d.length != 0
         f = "#{d}/#{p}"
         return f if File.executable?(f)
         d.gsub!(/\/[^\/]*$/, '')
     end

     return nil
end

puts find_program_hierarchically('main.rb')
puts find_program_hierarchically('nonesuch')
puts find_program_hierarchically('hello.txt')

Yuck.

Thanks.

Try this simpler code:

require 'pathname'

class Pathname
def ancestors
   return [self] if self==parent
   return [self] + parent.ancestors
end
end

def find_program_hierarchically(p)
   dir=Pathname.getwd.ancestors.find {|d| (d+p).executable?} + p
end

I'm not convinced that's simpler. It's the same number of lines, brings
in an extra module, is recursive, and stuffs seven distinct identifiers
onto a single line. It does look nicer at first glance, though, since
it uses much less punctuation.

--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/

Jeffrey Schwab wrote:

Trans wrote:
> Thanks Jeffrey and Ken. I was thinking maybe there was a util for this
> already but I suppose not. I wrote code like this:
>
> Dir.chdir('..') until File.exectuable?( file )
>
> It does change the directory, but for my purposes that's okay. See any
> problems with that? Work with Windows okay?

It'll loop forever if the file doesn't exist.

  Dir.chdir('..') until File.exectuable?( file ) or Dir.pwd == '/'

Will that work on Windows? If not what do I need to match?

Thanks,
T.

Does Pathname.getwd.parent==Pathname.getwd work on Windows?
I didn't realize there was Pathname.root? for me to use it would probably
have simplified things in my code a lot.

--Ken

···

On Sun, 13 Aug 2006 23:36:51 +0000, Jeffrey Schwab wrote:

Trans wrote:

Jeffrey Schwab wrote:

Trans wrote:

Thanks Jeffrey and Ken. I was thinking maybe there was a util for this
already but I suppose not. I wrote code like this:

  Dir.chdir('..') until File.exectuable?( file )

It does change the directory, but for my purposes that's okay. See any
problems with that? Work with Windows okay?

It'll loop forever if the file doesn't exist.

  Dir.chdir('..') until File.exectuable?( file ) or Dir.pwd == '/'

Will that work on Windows? If not what do I need to match?

'Fraid not. Windows filesystems don't allow mounting the way Unix
filesystems do, so you end up with multiple "root" directories whose
names include letters and colons. E.g., you probably know that the hard
drive of most PCs is called "C:\".

Pathname.root? seemed promising, but it doesn't work properly on
Windows, either. Windows isn't a very good collection of operating
systems, and I think most Ruby developers are smart enough to avoid it.

--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/

Jeffrey Schwab wrote:

Not quite, but it's a great idea! You might want to sit down for this one:

     C:\>ruby -rpathname -e 'puts Pathname.getwd'
     C:/

     C:\>ruby -rpathname -e 'puts Pathname.getwd.parent'
     C:/..

Could you live with something like this, or are the regex/string
manipulation/punctuation just too ugly?

     file = ARGV.shift

     Dir.chdir('..') until File.executable?(file) or
         Dir.getwd =~ /^(?:\w:)?[\/\.]*$/

     puts Dir.getwd.gsub(/\/$/, '') + '/' + file if File.executable?(file)

Guess I don't have much of choice. Pretty sad choice though. I can't
beleive there's not a cleaner solution.

T.

Jeffrey Schwab wrote:

Trans wrote:
> Jeffrey Schwab wrote:
>> Not quite, but it's a great idea! You might want to sit down for this one:
>>
>> C:\>ruby -rpathname -e 'puts Pathname.getwd'
>> C:/
>>
>> C:\>ruby -rpathname -e 'puts Pathname.getwd.parent'
>> C:/..
>>
>> Could you live with something like this, or are the regex/string
>> manipulation/punctuation just too ugly?
>>
>> file = ARGV.shift
>>
>> Dir.chdir('..') until File.executable?(file) or
>> Dir.getwd =~ /^(?:\w:)?[\/\.]*$/
>>
>> puts Dir.getwd.gsub(/\/$/, '') + '/' + file if File.executable?(file)
>
> Guess I don't have much of choice. Pretty sad choice though. I can't
> beleive there's not a cleaner solution.

Well, you could always write your own, more WinFriendly module, in which
path.root? and friends worked more like one would expect. It's more
code up front, but it only has to be written once.

I'm not going to bother with a whole module. It's been done before.
Actually I'm suprised that Daniel Berger's work on Pathname2 hasn't
found it's way back to imporving Ruby's built in Pathname class.
Appearently he put a lot of effort into better Windows support.

Think I'll just write FileTest.root?( dir ) and make due.

T.

Jeffrey Schwab wrote:

Excellent. I would appreciate it if you would post the code.

Hmmm... What does:

  File.expand_path('/')

produce on a Windows machine?

Sometimes I forget that Ruby zeitgeist lets us add methods at will to
existing packages. In my native land of C++, client code is
specifically prohibited from messing with the standard (std::slight_smile: namespace.

Yep Yep.

T.

Jeffrey Schwab wrote:

Trans wrote:
> Hmmm... What does:
>
> File.expand_path('/')

Eureka.

irb(main):001:0> File.expand_path('/')
=> "C:/"
irb(main):002:0> File.expand_path('C:/..')
=> "C:/"

Let ty this:

  def FileTest.root?(dir)
    pth = File.expand_path(dir)
    return true if pth == '/'
    return true if pth =~ /^(\w:)?\/$/
    false
  end

The == line should give a slight speed boost to unix systems.

T.

Why not use this code to redefine Pathname.root?

--Ken

···

Jeffrey Schwab <jeff@schwabcenter.com> wrote:

Trans wrote:

Jeffrey Schwab wrote:

Trans wrote:

Let ty this:

  def FileTest.root?(dir)
    pth = File.expand_path(dir)
    return true if pth == '/'
    return true if pth =~ /^(\w:)?\/$/
    false
  end

The == line should give a slight speed boost to unix systems.

Looks good.

def FileTest.root?(dir)
    pth = File.expand_path(dir)
    return true if pth == '/'
    return true if pth =~ /^(\w:)?\/$/
    false
end

file = ARGV.shift

Dir.chdir('..') until File.executable?(file) or FileTest.root?(Dir.getwd)

puts Dir.getwd.gsub(/\/$/, '') + '/' + file if File.executable?(file)

--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/