I've encountered the following command:
source foo -c configs/foo.config
What is -c flag is actually may do here? foo is bash script, foo.config also looks like one.
The source command is a bash-specific alias for the POSIX-standardized command .. The specific usage you're asking about is mentioned by POSIX as an allowable extension:
The KornShell version of dot takes optional arguments that are set to the positional parameters. This is a valid extension that allows a dot script to behave identically to a function.
Thus, when code read from foo is invoked, its $1 will be -c and its $2 will be configs/foo.config.
This is also explicitly documented if you run help source in bash:
source: source filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.
Note the text above: If any ARGUMENTS are supplied, they become the positional parameters when FILENAME is executed.
Related
I would like to know what does the command source do. I have tried:
whatis
$ whatis source
source: nothing appropriate.
man
$ man source
No manual entry for source
source (-h, --help, etc...)
$ source
source: not enough arguments
But it seems no documentation about it.
I commonly use it to save any changed on my dotfiles, but what does it exactly do? Why there is not documentation about it?
source is a bash shell built-in command that executes the content of the file passed as an argument, in the current shell. It has a synonym in . (period).
Syntax
. filename [arguments]
source filename [arguments]
From the source manual
source filename [arguments]
Read and execute commands from filename in the current shell environment and
return the exit status of the last command executed from filename. If
filename does not contain a slash, file names in PATH are used to find the
directory containing filename. The file searched for in PATH need not be
executable. When bash is not in posix mode, the current directory is
searched if no file is found in PATH. If the sourcepath option to the short
builtin command is turned off, the PATH is not searched. If any arguments
are supplied, they become the positional parameters when filename is
executed. Otherwise the positional parameters are unchanged. The return
status is the status of the last command exited within the script (0 if no
commands are executed), and false if filename is not found or cannot be
read.
Be careful! ./ and source are not quite the same.
./script runs the script as an executable file, launching a new shell to run it
source script reads and executes commands from filename in the current shell environment
Note: ./script is not . script, but . script == source script
Is there any difference between source in bash after all?
I have used the command alias filecreate='touch $1' in my script to create a new file in my present working directory with the help of filecreate as custom command. But when I execute the script it's showing error. Also how do I make the command to accept 2 parameters one the filename and other the pathname.
alias filecreate=touch
or its function equivalent:
filecreate(){ touch "$#"; }
will accept an arbitrary number of arguments and pass them to touch.
Positional argument expansions usually don't belong in aliases, as aliases, unlike functions, don't get their own positional argument arrays.
Aliases are simple text expansions.
Your
alias filecreate='touch "$1"'
when run like so:
filecreate SomeFile
would simply expand to
filecreate "$1" SomeFile #$1 comes from the caller
This differs from functions and scripts, which do get their own argument array.
I am calling a script2.sh from script1.sh without passing parameter. But I am passing parameter to script1.sh. I am trying to print first parameter of script2.sh.
script1.sh
#! /bin/bash
PRM1=$1
source script2.sh
script2.sh
#! /bin/bash
PRM1=$1
echo "$PRM1"
output is
# source script1.sh hello
#hello
#
But Ideally
# source script1.sh hello
#
Can any one tell me why script2.sh is taking script1.sh parameter as it's parameter?
From the bash(1) man page:
SHELL BUILTIN COMMANDS
source filename [arguments]
Read and execute commands from filename in the current shell environment and return the exit status of the last command executed from filename. If filename does not contain a slash, file names in PATH are used to find the directory containing filename. The file searched for in PATH need not be executable. When bash is not in posix mode, the current directory is searched if no file is found in PATH. If the sourcepath option to the shopt builtin command is turned off, the PATH is not searched. If any arguments are supplied, they become the positional parameters when filename is executed. Otherwise the positional parameters are unchanged. The return status is the status of the last command exited within the script (0 if no commands are executed), and false if filename is not found or cannot be read.
pass junk as parameter. so that the positional parameter will replace with it.
You are not giving your script1.sh any argument as it is expecting one. (A small note, I always close the white space in this line: #!/bin/bash - not #! /bin/bash). In your script1.sh, try this:
#!/bin/bash
PRM1=$1
./script2.sh $PRM1
I current read this line from our configure.ac build script. I have search on Google for answer but not find it.
I assume it is shell script but what does this means, especially for -- ?
set -- "$progname" "$#"
From help set:
-- Assign any remaining arguments to the positional parameters.
If there are no remaining arguments, the positional parameters
are unset.
The reason for -- is to ensure that even if "$progname" or "$#" contain dashes, they will not be interpreted as command line options.
set changes the positional parameters, which is stored in $#. So in this case, it appends "$progname" to the beginning of the positional parameters received by the script.
The -- is a bash built-in as well as something a lot of unix commands use to denote the end of command options. So if you have something like:
grep -- -v file
the -v won't be interpreted as a grep option, but a parameter (so you can grep for -v).
The $# is the list of all the parameters that are passed into the script (which I assume the set command is a part of).
The -- ensures that whatever options passed in as part of the script won't get interpreted as options for set, but as options for the command denoted by the $progname variable.
Suppose I write a function in a bash script, with the name of an available binary, say, pwd:
function pwd(){
echo '/'
}
Alright, that seems a bit weird, but the question is: what will happen if further in my script I write the commands:
cd /usr
pwd
What pwd will be used? Also, how can I force the use of the other one?
Your function will get called because it hides the pwd builtin.
To force the command to be executed, use the command builtin:
command pwd
From bash manual:
command [-pVv] command [arg ...]
Run command with args suppressing the normal shell function
lookup. Only builtin commands or commands found in the PATH are
executed. If the -p option is given, the search for command is
performed using a default value for PATH that is guaranteed to
find all of the standard utilities. If either the -V or -v
option is supplied, a description of command is printed. The -v
option causes a single word indicating the command or file name
used to invoke command to be displayed; the -V option produces a
more verbose description. If the -V or -v option is supplied,
the exit status is 0 if command was found, and 1 if not. If
neither option is supplied and an error occurred or command can-
not be found, the exit status is 127. Otherwise, the exit sta-
tus of the command builtin is the exit status of command.
Function will have precedence. You can check it easily using type pwd.
Considering that pwd is a builtin, you can reach the real implementation using builtin pwd.
If you want to actually get the executable from your system, you can refer to its path, e.g. using $(which pwd).
Functions take precedence over path search. Use the full path to avoid inboking the function. The builtin keyword provides a similar facility for Bash's built-in keywords (echo, cd, etc)