-1

This is the situation:

I have a ruby file named file1.rb

This file can be located anywhere, but we knows that the path ends with /foo/bar/file1.rb.

I want to create a bash-alias that lets me run this file from any directory on the machine. It must also be possible to pass command line arguments to the program when running it.

So instead of writing:

ruby unknown_path/foo/bar/file1.rb argument.txt

I want to write:

alias argument.txt

Is this possible?

Barmar
  • 741,623
  • 53
  • 500
  • 612
alexander
  • 5
  • 3
  • Does this answer your question? [what is the use of "#!/usr/local/bin/ruby -w" at the start of a ruby program](https://stackoverflow.com/questions/17447532/what-is-the-use-of-usr-local-bin-ruby-w-at-the-start-of-a-ruby-program) – Max Mar 27 '23 at 15:33
  • Specifically, adding a shebang to the script lets you make it executable and run the script directly via the shell. – Max Mar 27 '23 at 15:35
  • @Max What does that have to do with it? The unknown location is the script, not `ruby`. – Barmar Mar 27 '23 at 15:38
  • 1
    If the file can truly be anywhere on the system, you'll need to use the `find` command to find it. But what should happen if there are multiple copies? – Barmar Mar 27 '23 at 15:40
  • the normal approach would be to add the directory(ies) (where `file1.rb` is located) to your `PATH` (I'm assuming `file1.rb` is executable); but if `file1.rb` can be located *anywhere* (different filesystems, different directories) on the host then you're left with running a `find` to first locate the file, and in this case your best bet will likely be a function (instead of an alias); the function is going to include the same steps you currently perform to find the location of `file1.rb` – markp-fuso Mar 27 '23 at 15:43
  • 1
    Why is the path actually unknown? This sounds like a dangerous way to run a script. There's a reason why the `PATH` env var exists (and why `.` is usually not added to it anymore): to prevent running untrusted binaries from arbitrary locations on the file system. – Max Mar 27 '23 at 15:47
  • 1
    stepping back from the requirement for a minute ... how is this file being installed and how can it end up in *any* directory on the host? is this by any chance distributed in a `tar/zip` file and you have no control of where the user extracts the contents? if this is the case, perhaps distribute the file as a shell script (aka self-extracting file) that has some logic to either a) install the file under a common location (eg, `~/bin/file1.rb`) or b) determine the extract directory and add this to the user's `PATH` (via `~/.bashrc` or `~/.profile`) – markp-fuso Mar 27 '23 at 15:47
  • A proper answer would be, don't use an alias, and don't install the file in an unknown location. If the user is allowed to select where they want it installed, add that location to their PATH. – tripleee Mar 27 '23 at 15:58
  • This is not a big project, it’s a hobby project, I have not used a lot of Bash before and I don’t know how PATH works. How can I solve this in a better way? With any folder I just mean that if people clone my git repo it should work for them aswell. – alexander Mar 27 '23 at 16:16

4 Answers4

3

Anyone cloning your repository can clone it anywhere, and hard-coding the path to an executable is considered an anti-pattern. What you most likely are trying to do is to call an executable from inside the project directory where the file was cloned. You should probably assume that anyone who can clone your project is capable of changing to a project directory, or at least read the README file you include explaining where to install the binaries and run the code.

If you're distributing your Ruby file as a gem named "foo", then there's a standard gem layout that allows you to use require or require_relative from the project's ./lib/foo.rb. You can also modify the $LOAD_PATH of your Ruby program if you are putting libraries in unusual places.

If you're doing something else, then you might want to look at utilities like direnv that lets a user modify their shell PATH dynamically when they enter a project directory. This is useful because it also unsets the changes when they leave the project directory.

Finally, if you're distributing your code as a gem, then once the gem is properly installed into GEM_HOME the user shouldn't have to worry about the location of executables within the gem. They should either be exposed when the user invokes require "foo" or calls an executable installed into the gem's bin directory, which your Ruby version manager should expose in PATH via GEM_HOME, e.g. $HOME/.gem/ruby/3.2.1/foo/bin/file1.

In short, there are a lot of standard ways to invoke a Ruby source file, but shell aliases probably aren't the right way for the use case you described. PATH and CDPATH are the most likely environment variables to modify for Bash, and LOAD_PATH is the most likely setting to modify for Ruby itself. If you can, though, stick with the standards, and make sure to note any oddities in your project's README.

Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199
0

You can use the locate command to search for a file whose pathname contains a string.

alias run_file1='ruby $(locate /foo/bar/file1.rb)'

This assumes you're running the daily cron job that updates the locate database.

Barmar
  • 741,623
  • 53
  • 500
  • 612
0

The alias would be:

alias do_file1='ruby "$FILE1_HOME/foo/bar/file1.rb"'

and require any user to have:

export FILE1_HOME=/some/directory

in their .profile or similar before using that alias where /some/directory is wherever they installed /foo/bar/file1.rb under.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
0

I would recommend looking into how to update PATH and such for ruby programs as mentioned in earlier comments. But if you want to continue with a bash-script solution to this then I would recommend that you use a bash function and not a bash alias. Bash functions are more flexible than an alias and makes for easier handling of arguments.

function run_ruby() {

# find the ruby file
# ugly since you are searching from the root dir which may be large search space. 
# Better to specify the exact path to the file or at least a few possible locations. I leave this task for you :)
rb_file="$(find / -iname file1.rb)"

# $1 is the first arg to the "run_ruby" function
ruby "$rb_file" "$1"

}

After putting this in your .bashrc and sourcing then you can run like this:

$ run_ruby arguments.txt
copyclan
  • 1
  • 1