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 3 '18 at 6:02
  • To execute a list of quite unrelated scripts (which are all in the same directory), in the current Bash process. – user9303970 Feb 3 '18 at 6: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 3 '18 at 6: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 3 '18 at 6: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 3 '18 at 6:35
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).

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.