1

I wrote this here-document to source a few scripts under the path ~/own_scripts/ but I wrote it in a way that causes duplication of this path:

source <<-EOF
  ~/own_scripts/1.sh
  ~/own_scripts/2.sh
  # More scripts under ~/own_scripts;
EOF

Setting and later unsetting a variable with the path is nice but would still result in redundancy.

What's the best way to avoid path redundancy in such source (or bash) here-document?

  • 1
    What exactly do you expect that to do, and what are you trying to do? – Michael Homer Feb 03 '18 at 06:02
  • To execute a list of quite unrelated scripts (which are all in the same directory), in the current Bash process. – Arcticooling Feb 03 '18 at 06:11
  • 1
    Well what it does is output bash: source: filename argument required to standard error, so you've probably got something else to fix first, but I don't think I understand what the other issue you're really asking about is. – Michael Homer Feb 03 '18 at 06:13
  • 1
    I don't understand this HEREing too. . ~/own_scripts/1.sh is shorter than that. Or for i in {1..6}; do source ~/own_scripts/$i.sh; done or for f in ./{a,b}.sh ; do source $f; done. If you need to activate and deactivate it without commenting always 10, 20 lines out, put the call into a function, and activate/deactivate the function call only. – user unknown Feb 03 '18 at 06:33
  • Are you concerned, that variable assignments in each script are redundant? From a performance perspective? Or is a variable like the PATH growing and growing by every script? – user unknown Feb 03 '18 at 06:35
  • @userunknown I just don't want to repeat myself either with full path, or variable expansions. I want to use the path only once in the total meaning of that sense. – Arcticooling Feb 03 '18 at 06:58
  • So all the scripts define the path and all in the same way? Do you need those scripts outside of this script under discussion? We have no clear idea why you don't want it, what's the goal, what the circumstances. You can once and for all copy all files into your script and eliminate redundancy by hand, but it is a terrible idea, if the other scripts get updated, and you have to perform the updates in this script too. You can check in every subscript, whether path or variables are already set, but this will cost time and space and clutter your code. – user unknown Feb 03 '18 at 07:12
  • @userunknown Sourcing a here-document that calls the scripts is semantically different from sourcing the scripts in a loop. The difference lies in what environment the scripts under $HOME/onw_scripts are executing in (the current shell environment or their own shell environment). – Kusalananda Feb 03 '18 at 07:26

1 Answers1

1

A here-document is just a document. A script in a here-document is just a script.

Your script could be written

cd "$HOME/own_scripts" || exit 1
./1.sh
./2.sh

Or, if all the scripts that you'd like to invoke are called n.sh with n ranging from 1 to, say, 30:

cd "$HOME/own_scripts" || exit 1
for (( i = 1; i <= 30; ++i )); do
    [ -x "${i}.sh" ] && ./${i}.sh
done

That is,

source <<-'END_SCRIPT'
    cd "$HOME/own_scripts" || exit 1
    for (( i = 1; i <= 30; ++i )); do
        [ -x "${i}.sh" ] && ./${i}.sh
    done
END_SCRIPT

In fact, since the here-document now is pretty short, you could get rid of the cd again:

source <<-'END_SCRIPT'
    for (( i = 1; i <= 30; ++i )); do
        [ -x "$HOME/own_scripts/${i}.sh" ] && "$HOME/own_scripts/${i}.sh"
    done
END_SCRIPT

Only, source does not read from standard input... so sourcing the here-document won't work to start with.

Instead, use something like

bash <<-'END_SCRIPT'
    ...as above...
END_SCRIPT

(if bash is the shell you want to run the script with).

  • I've used 'END_SCRIPT' to start the here-document. The quoting stops the current shell from expanding variables within the document, and the more verbose tag serves as documentation to the reader.

  • I've used $HOME rather than ~ since tilde does not behave like a variable and the more verbose $HOME serves better as documentation in scripts.

  • The script in the here-document simply uses cd to change directory to the $HOME/onw_script directory. If that fails, the shell session is terminated.

  • In the examples with the for-loop (which will work in bash and ksh shells), I generate the name of the script to execute in the loop. I also test whether there's actually an executable file available with that name before trying to execute it (with th -x test).

Kusalananda
  • 333,661