How to auto source a shell script?

3

2

How to make a shell script execute it's commands as source commands without having to use "source scriptname.sh" expression to launch the script? Basically what I want is to type ./scriptname.sh and it's commands to act as if source was used to execute the shell-script.

Andrew-George Hondrari

Posted 2012-12-05T15:38:30.257

Reputation: 211

Do you just want to execute the commands in the script? – terdon – 2012-12-05T16:01:25.943

no, I want them to act as source shell commands, without using the source keyword in the execution call – Andrew-George Hondrari – 2012-12-05T16:03:46.830

2Could you post your script (or the relevant parts of it) so we can better understand what you are trying to do please? Also, please explain why you do not want to use source. – terdon – 2012-12-05T16:12:21.213

2If it is just the amount of typing you want to avoid, note that the syntax . file is equivalent to source file Actually, source is a "bashism" (Bash specific) and the dot operator is "standard" (POSIX). – Daniel Andersson – 2012-12-05T17:24:46.773

@Daniel The source command is originally from Bill Joy's csh.

– Nicole Hamilton – 2012-12-05T17:50:57.390

@NicoleHamilton: Ah, I did not know that. I've only heard it described as a "bashism" in discussions during Debian's great Bash→Dash migration. – Daniel Andersson – 2012-12-05T20:23:06.840

Answers

4

None of the Unix shells allow you to mark a script as one that should always be sourced the way you're hoping. What I would do is create an alias or procedure to do what you want and put it in my startup script. For example, in tcsh:

alias scriptname source \!\!

In bash, you could write it as a procedure:

scriptname( ) { source scriptname.sh $*; }

Nicole Hamilton

Posted 2012-12-05T15:38:30.257

Reputation: 8 987

use "$@" instead of $* -- the former is the only safe way to pass parameters that might contain whitespace. – glenn jackman – 2012-12-05T21:23:05.393

0

You can use a feature of bash that allows you to intercept user input and act on it, overriding any usual command execution.

Add the following to your bash startup script:

shopt -s extdebug
function auto_source_names {
    local CMD=$BASH_COMMAND
    if [[ -f "$CMD" ]] && [[ ! -x "$CMD" ]] ; then
        source "$CMD"
        return 1
    else
        return 0
    fi
}
trap 'auto_source_names' DEBUG

This causes the function to be called for every command executed. If it's the name of a file that isn't executable (otherwise we'd block legitimate ./foo.sh calls as well), it is sourced and no command executed. Be aware of files named ls or rm in the same directory. You could add additional safeguards, e.g. requiring .sh file extension or file telling you the name is a text file.


Example:

Create foo.sh:

FOO=bar

Then:

$ echo $FOO
$ foo.sh
$ echo $FOO
bar

Daniel Beck

Posted 2012-12-05T15:38:30.257

Reputation: 98 421

I concede it's a clever solution, but is it really advisable to, in effect, change the language default from isolating scripts in a separate process to sourcing them instead? Seems like this might break a lot of stuff. I would treat the need to source a script as the exception rather than the rule, but make it easy to type when I encounter one. – Nicole Hamilton – 2012-12-05T18:25:05.620

@Daniel: This fails if the user tries to invoke the command file (script) with arguments, as in foo.sh barrel, because BASH_COMMAND (and consequently CMD) gets set to the entire simple command, and thus the –f test fails.  I suggest that you add eval set –– "$CMD" and do the –f test on $1; then source "$@". – Scott – 2013-01-10T02:28:43.487

@Daniel: Your statement, “Be aware of files named ls or rm in the same directory.” could be broadened: “Be aware that non-executable files in the current directory will totally pre-empt the normal command processing logic of the shell.”  I say that because even (non-executable) files such as alias, export, history, jobs, etc…, will be sourced, ignoring and overriding their definition as builtin commands. – Scott – 2013-01-10T02:30:45.563

@Nicole: I agree with you on two counts out of three: (1) it’s a clever solution, and (2) I believe it is inadvisable.  But (3) (unless I’m overlooking or misinterpreting something) @Daniel’s solution doesn’t change the default shell behavior from isolating scripts in a separate process to sourcing them instead.  Note the [[ ! –x "$CMD" ]] factor –– scripts that have executable mode set will fall out of auto_source_names with a return code of 0 (zero), telling the shell to process them normally. – Scott – 2013-01-10T02:34:03.380

@Nicole: FYI, my concern is that this technique is too inclusive.  (I heartily endorse @Daniel’s suggestion to require a .sh extension.)  I’d be afraid of typing something like conv.c when I meant cc conv.c or vi conv.c, and having the shell source my C source file.  (I wouldn’t really expect anything in a C source file to be a valid Unix command, but I wouldn’t want to find out the hard way, either.) – Scott – 2013-01-10T02:35:08.920

-3

The first line needs to contain the path to the interpreter:
#! /bin/bash

Then make the script file executable:
chmod +x scriptname.sh

Now you can run ./scriptname.sh to execute it.

idoimaging

Posted 2012-12-05T15:38:30.257

Reputation: 214

1this is basic execution, I asked something else – Andrew-George Hondrari – 2012-12-05T16:03:13.597

@AndreiGeorgeHondrari, it appears that most are not fammilar with your 'source shell commands' (I have years of experience with linux and never heard of such). perhaps you could explain what you want a little better. – Frank Thomas – 2012-12-05T16:51:26.057

@Frank Thomas , http://bash.cyberciti.biz/guide/Source_command . See what Nicole Hamilton answered. That's the solution.

– Andrew-George Hondrari – 2012-12-05T16:53:27.310

thank you, that was very informative. from the article you linked, you can include a 'source' statement in the driver script just below the shebang, and then call the driver script withput specifing 'source'. Do you have a driver script, or are you just trying to call a function in a source script file directly from the CLI? – Frank Thomas – 2012-12-05T17:04:10.187

@Frank When you run a script the usual way as a command, the shell forks a copy of itself as a new process to run the script. That isolates whatever that script does from the copy of the shell you're using interactively. If the script changes the environment variables or current directory, all of that's lost when the script exits. It doesn't change the state of the copy of the shell you're interacting with. The source statement causes the script to be run without forking to create that isolation. All the commands in the script are run by your copy of the shell and can change its state. – Nicole Hamilton – 2012-12-05T18:00:42.340

@Frank Thomas, you mean using #!/bash/bin; source ? – Andrew-George Hondrari – 2012-12-06T12:45:59.380

yes, that seems to be the main use of source per your link, (to include another file so that its methods may be used). sorry if I misunderstood your issue. – Frank Thomas – 2012-12-06T12:51:19.730