Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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.

share|improve this question
    
Do you just want to execute the commands in the script? –  terdon Dec 5 '12 at 16:01
    
no, I want them to act as source shell commands, without using the source keyword in the execution call –  Andrei George Hondrari Dec 5 '12 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 '12 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). –  Daniel Andersson Dec 5 '12 at 17:24
    
@Daniel The source command is originally from Bill Joy's csh. –  Nicole Hamilton Dec 5 '12 at 17:50
show 1 more comment

3 Answers

up vote 4 down vote accepted

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 $*; }
share|improve this answer
    
use "$@" instead of $* -- the former is the only safe way to pass parameters that might contain whitespace. –  glenn jackman Dec 5 '12 at 21:23
add comment

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
share|improve this answer
    
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 Dec 5 '12 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 "$@". –  Scott Jan 10 '13 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. –  Scott Jan 10 '13 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. –  Scott Jan 10 '13 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.) –  Scott Jan 10 '13 at 2:35
add comment

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.

share|improve this answer
1  
this is basic execution, I asked something else –  Andrei George Hondrari Dec 5 '12 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. –  Frank Thomas Dec 5 '12 at 16:51
    
@Frank Thomas , bash.cyberciti.biz/guide/Source_command . See what Nicole Hamilton answered. That's the solution. –  Andrei George Hondrari Dec 5 '12 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? –  Frank Thomas Dec 5 '12 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. –  Nicole Hamilton Dec 5 '12 at 18:00
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.