# Shell scripting & Windows/Linux Paths

**URL:** <https://www.ruby-forum.com/t/shell-scripting-windows-linux-paths/162507>\
**Category:** Ruby\
**Created:** [March 10, 2009, 5:21pm UTC](https://www.ruby-forum.com/t/shell-scripting-windows-linux-paths/162507 "2009-03-10T17:21:24Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![juan\_zanos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/4da419/32.png) [@juan\_zanos](https://www.ruby-forum.com/u/juan_zanos)\
**Post date:** [March 10, 2009, 5:21pm UTC](https://www.ruby-forum.com/t/shell-scripting-windows-linux-paths/162507/1 "2009-03-10T17:21:24Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![juan\_zanos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/4da419/32.png) [@juan\_zanos](https://www.ruby-forum.com/u/juan_zanos)\
**Post date:** [March 10, 2009, 5:30pm UTC](https://www.ruby-forum.com/t/shell-scripting-windows-linux-paths/162507/2 "2009-03-10T17:30:50Z")

</div>

2009/3/10 Juan Z. [removed\_email\_address@domain.invalid](mailto: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

---

<div class="post-metadata">

**Author:** ![juan\_zanos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/4da419/32.png) [@juan\_zanos](https://www.ruby-forum.com/u/juan_zanos)\
**Post date:** [March 10, 2009, 5:35pm UTC](https://www.ruby-forum.com/t/shell-scripting-windows-linux-paths/162507/3 "2009-03-10T17:35:34Z")

</div>

Robert K. wrote:

> 2009/3/10 Juan Z. [removed\_email\_address@domain.invalid](mailto: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.

---

<div class="post-metadata">

**Author:** ![juan\_zanos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/4da419/32.png) [@juan\_zanos](https://www.ruby-forum.com/u/juan_zanos)\
**Post date:** [March 10, 2009, 5:55pm UTC](https://www.ruby-forum.com/t/shell-scripting-windows-linux-paths/162507/4 "2009-03-10T17:55:33Z")

</div>

Juan Z. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> > 2009/3/10 Juan Z. [removed\_email\_address@domain.invalid](mailto: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.

---

<div class="post-metadata">

**Author:** ![juan\_zanos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/4da419/32.png) [@juan\_zanos](https://www.ruby-forum.com/u/juan_zanos)\
**Post date:** [March 10, 2009, 5:36pm UTC](https://www.ruby-forum.com/t/shell-scripting-windows-linux-paths/162507/5 "2009-03-10T17:36:44Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![juan\_zanos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/4da419/32.png) [@juan\_zanos](https://www.ruby-forum.com/u/juan_zanos)\
**Post date:** [March 10, 2009, 10:32pm UTC](https://www.ruby-forum.com/t/shell-scripting-windows-linux-paths/162507/6 "2009-03-10T22:32:41Z")

</div>

> 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.

---

<div class="post-metadata">

**Author:** ![juan\_zanos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/4da419/32.png) [@juan\_zanos](https://www.ruby-forum.com/u/juan_zanos)\
**Post date:** [March 10, 2009, 9:08pm UTC](https://www.ruby-forum.com/t/shell-scripting-windows-linux-paths/162507/7 "2009-03-10T21:08:37Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![juan\_zanos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/4da419/32.png) [@juan\_zanos](https://www.ruby-forum.com/u/juan_zanos)\
**Post date:** [March 11, 2009, 11:10am UTC](https://www.ruby-forum.com/t/shell-scripting-windows-linux-paths/162507/8 "2009-03-11T11:10:58Z")

</div>

Michael M. [removed\_email\_address@domain.invalid](mailto: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)))
