Shell scripting & Windows/Linux Paths


#1

What’s the best way to launch executables with Ruby in a way that
paths and other command line parameters work on both Windows and Linux?

Juan


#2

2009/3/10 Juan Z. removed_email_address@domain.invalid:

What’s the best way to launch executables with Ruby in a way that paths and
other command line parameters work on both Windows and Linux?

I’m not sure why you are asking for “other command line parameters”
but for paths forward slashes as separators are OK on both platforms.

Kind regards

robert


#3

Robert K. wrote:

2009/3/10 Juan Z. removed_email_address@domain.invalid:

What’s the best way to launch executables with Ruby in a way that paths and
other command line parameters work on both Windows and Linux?

I’m not sure why you are asking for “other command line parameters”
but for paths forward slashes as separators are OK on both platforms.

For relative paths only. A path beginning with / will be misinterpreted
as a command-line switch by most Windows commands.


#4

Juan Z. removed_email_address@domain.invalid writes:

2009/3/10 Juan Z. removed_email_address@domain.invalid:

What’s the best way to launch executables with Ruby in a way that
paths and
other command line parameters work on both Windows and Linux?
Yes, I’m mostly concerned with paths. I’d like to write everything
in Unix style and just have it automatically converted somehow so
everything stays relatively legible.

IMO, the best way is not to use any literal path.

Keep a map of executable => path that you load at startup from a
different configuration file (or source) depending on whether you run
on Microsoft Windows or on Unix. Actually this would even allow you
to adapt your program to different Unix systems, with different
“standard” places for the various executables.

If you try that, you will see that it gives you some level of
abstraction in the management of pathnames so your program becomes
even clearer.


#5

Yes, I’m mostly concerned with paths. I’d like to write everything
in Unix style and just have it automatically converted somehow so
everything stays relatively legible.


#6

Yes, I’m mostly concerned with paths. I’d like to write everything
in Unix style and just have it automatically converted somehow so
everything stays relatively legible.

You shouldn’t write a filename or whatever in unix style. Ruby has
excellent libraries for dealing with pathnames. Take a look at the
File and the Pathname classes, which provide everything you need for
writing cross-plattform apps, and use the methods they provide.


#7

Juan Z. wrote:

Yes, I’m mostly concerned with paths. I’d like to write everything
in Unix style and just have it automatically converted somehow so
everything stays relatively legible.

One good pattern for dealing with this I have seen is simply to have a
shell_command method somewhere, so you can do different things if you’re
on different OSs. And to figure out dynamically which OS you’re working
with, use this:

require ‘rbconfig’
if Config::CONFIG[“target_os”] == ‘linux’
OS = ‘linux’
else
OS = ‘windows’ #presumably
end

Yes, I am aware that that code is specific to linux/windows but it was
enough for me. You’re a puts call away from getting the required
options. That sort of thing can make life easier if you want to
redirect to /dev/null or NUL and only want to change your command in one
place.

Michael

=======================================================================
This email, including any attachments, is only for the intended
addressee. It is subject to copyright, is confidential and may be
the subject of legal or other privilege, none of which is waived or
lost by reason of this transmission.
If the receiver is not the intended addressee, please accept our
apologies, notify us by return, delete all copies and perform no
other act on the email.
Unfortunately, we cannot warrant that the email has not been
altered or corrupted during transmission.


#8

Michael M. removed_email_address@domain.invalid writes:

redirect to /dev/null or NUL and only want to change your command in one
place.

It would be much better to have subclasses for each OS. This way, you
could generate commands for one OS, from another OS, and send it
remotely thru ssh or some other way.

(class OS
(def genGetRootDirectory
(subclassResponsibility)
end)
(def genGetListOfDirectoriesInDirectory(directory)
(subclassResponsibility)
end)
(def genGetListOfFilesInDirectory(directory)
(subclassResponsibility)
end)
(def genRemoteExecute(command)
(subclassResponsibility)
end)
(def execute(command)
(subclassResponsibility)
end)
end)

(class Linux < OS
(def genGetRootDirectory
(Directory . new “/”)
end)
(def genGetListOfDirectoriesInDirectory(directory)
(Command . new “find #{(quoteShellArgument (directory . path))}/*
-prune -type d -print”)
end)
(def genGetListOfFilesInDirectory(directory)
(Command . new “find #{(quoteShellArgument (directory . path))}/*
-prune \( \! -type d \) -print”)
end)
(def genRemoteExecute(command,host,user=nil)
(Command . new “ssh #{(user ? user+”@" : “”)}#{host} #{(command .
text)}")
end)
(def execute(command)
(system (command . text))
end)
end)

and similarly for MSWindows.

So you can write:

(localHost = ((Config::CONFIG[“target_os”] == ‘linux’) ? (Linux . new) :
(MSWindows . new)))
(remoteDoze = (MSWindows . new))
(remoteLinux = (Linux . new))

(localHost . execute (localHost . genRemoteExecute (remoteDoze .
genGetListOfFiles (remoteDoze . genGetRootDirectory))))
(localHost . execute (localHost . genRemoteExecute (remoteLinux .
genGetListOfFiles (remoteLinux . genGetRootDirectory))))
(localHost . execute (localHost . genGetListOfFiles (localHost .
genGetRootDirectory)))