I have a folder /usr/bin/vendor/ which is added to PATH by convention and contains e.g. the shell script do_something.sh. Now I would like to add a subfolder /usr/bin/vendor/some_tool/ to additionally store one or more Perl scripts grouped together, because they have the same purpose and I need to additionally manage Eclipse project files, maybe even configuration files etc. In the end, I might get /usr/bin/vendor/some_tool/do_a.pl and /usr/bin/vendor/some_tool/do_b.pl.

Because of PATH, I can easily invoke do_something.sh everywhere. But is there some way to invoke some_tool/do_a.pl the same way? Really some_tool/do_a.pl with that relative path, so that I know I'm doing task do_a of some_tool. It's pretty much a wording/naming convention I would like to implement using the relative dir structure.

Tried that on the shell and it didn't work of course, but maybe there is something I'm doing wrong and it should work in general. But I guess it shouldn't and the only workaround would be to create a file /usr/bin/vendor/some_tool_do_a.sh which forwards all args to /usr/bin/vendor/some_tool/do_a.pl.


The bash man page specifies

   PATH   The  search  path for commands.  It is a colon-separated list of
          directories in which the shell looks for commands  (see  COMMAND
          EXECUTION  below).

It then goes on to say

   If  the name is neither a shell function nor a builtin, and contains no
   slashes, bash searches each element of the PATH for  a  directory  con‐
   taining  an  executable  file  by that name.

So the answer appears to be "No, what you want to do is not supported by bash."

| improve this answer | |
  • Accepting this answer while "only" upvoting others, because it's quoting the official docs and should therefore be the most correct one. – Thorsten Schöning Feb 2 '18 at 7:02

No, this is not possible: any / in your typed command makes it into an absolute path (if / is the first character), or a relative path with respect to your current directory, not a relative path within PATH entries.

A work-round might be to link all the scripts in /usr/bin/vendor/some_tool/ to /usr/bin/vendor/ with:

ln [-s] /usr/bin/vendor/some_tool/* /usr/bin/vendor/

Either hard or soft links could be used.

If you are always in the same work directory (or a small number of directories) when calling the script, then a simpler answer might be to create a relative link from this (or each) directory:

ln -s /usr/bin/vendor/some_tool .

In this case, you need to use symbolic link(s).

Other work-rounds might be to define a script with a short name to perform this function, which you would call with something like:

tl some_tool/do_a.pl

tl would parse the passed parameter, step through PATH looking for the script in each component, then invoke the full path to the script.

| improve this answer | |

What I do in the "main" script:

mydir=$(dirname "$0")

then the main script always finds the child, as long as they are moved together so that their relative position doesn't change.

| improve this answer | |
  • I don't see your point: am I missing something? 1) When writing a script, it is not much of a chore to enter a full path. 2) In any case, there is no indication that the questioner wanted to call the tool from an enclosing script. 3) You are not using any of the entries in the PATH variable, as the questioner said he wanted. – AFH Feb 1 '18 at 21:50
  • Read the OP question a bit fast I admit... OTH this is exactly how I would write your tl script, to avoid iterating the path. – xenoid Feb 2 '18 at 0:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.