3

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.

6
  • Do you just want to execute the commands in the script?
    – terdon
    Dec 5, 2012 at 16:01
  • no, I want them to act as source shell commands, without using the source keyword in the execution call Dec 5, 2012 at 16:03
  • 2
    Could 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
    Dec 5, 2012 at 16:12
  • 2
    If 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). Dec 5, 2012 at 17:24
  • @Daniel The source command is originally from Bill Joy's csh. Dec 5, 2012 at 17:50

3 Answers 3

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 $*; }
1
  • use "$@" instead of $* -- the former is the only safe way to pass parameters that might contain whitespace. Dec 5, 2012 at 21:23
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
5
  • 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. Dec 5, 2012 at 18:25
  • @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 "$@". Jan 10, 2013 at 2:28
  • @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. Jan 10, 2013 at 2:30
  • @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. Jan 10, 2013 at 2:34
  • @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.) Jan 10, 2013 at 2:35
-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.

7
  • 1
    this is basic execution, I asked something else Dec 5, 2012 at 16:03
  • @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. Dec 5, 2012 at 16:51
  • @Frank Thomas , bash.cyberciti.biz/guide/Source_command . See what Nicole Hamilton answered. That's the solution. Dec 5, 2012 at 16:53
  • 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? Dec 5, 2012 at 17:04
  • @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. Dec 5, 2012 at 18:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .