Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested `source` commands in my bash script?

Tags:

bash

I have the following setup

└── modules
    ├── main.sh
    ├── major.sh
    ├── sub-modules
    │   └── minor.sh
  • and I have added the path to /modules to $PATH.

all.sh:

source major.sh

major.sh:

source sub-module/minor.sh

But when I run this I get:

-bash: /sub-module/minor.sh: No such file or directory
like image 557
Ashley Coolman Avatar asked Oct 28 '15 19:10

Ashley Coolman


2 Answers

Yes. This is how the ./source operator works.

From the spec:

The shell shall execute commands from the file in the current environment.

If file does not contain a <slash>, the shell shall use the search path specified by PATH to find the directory containing file. Unlike normal command search, however, the file searched for by the dot utility need not be executable. If no readable file is found, a non-interactive shell shall abort; an interactive shell shall write a diagnostic message to standard error, but this condition shall not be considered a syntax error.

So when you use source file.sh the shell searches in the $PATH but when you use source dir/file.sh the $PATH lookup is skipped and dir is assumed to be relative to the current directory.

To do this sort of thing (internally to main.sh or major.sh) you could use Can a Bash script tell what directory it's stored in? to find the appropriate absolute path to use.

For general use you are going to need to stick them all in $PATH or source them from absolute/etc. paths.

like image 101
Etan Reisner Avatar answered Sep 28 '22 08:09

Etan Reisner


Path lookups only occur on names that don't contain a /. Also, only the immediate contents of a directory in PATH is checked, not all its subdirectories. With source sub-module/minor.sh, sub-module must be in the current directory. You would have to add /path/to/modules/sub-module to your path as well, then source minor.sh alone.

You can keep that to one line if you want:

PATH=/path/to/modules/sub-module:$PATH source minor.sh

This only updates PATH for this single source command.

like image 26
chepner Avatar answered Sep 28 '22 08:09

chepner