14

My understanding is that bash -c file means the same thing as being in an interactive bash shell and calling file, where bash file means to interpret the file using bash (as if it were a shell script). Is this accurate? Is this the reason you cannot run bash <executable> because it will try to interpret the file as a shell script instead of forking and running exec file?

2
  • 1
    Exactly. With bash -c you are simply giving it a line of a script whatever it is (including another executable script), and with bash file you are simply giving it a file that contains the script code. Because executable bash scripts are (through the use of #! directive) called by bash interpreter anyway, calling bash -c script.sh is like doing bash -c "bash script.sh".
    – orion
    Jan 15, 2015 at 16:12
  • @orion why not make that into an answer? Answering questions in comments is bad for everyone since the question will never be marked as answered.
    – terdon
    Jan 15, 2015 at 16:41

2 Answers 2

9

First, from bash documentation:

-c string

Read and execute commands from string after processing the options, then exit. Any remaining arguments are assigned to the positional parameters, starting with $0.

So when you supply -c option, bash treat string after -c as a sequence of commands, then execute those commands in the child process environment. So when you call bash -c file, bash treat file as a command, find it by looking through PATH environment variable. If file is found, then execute it, otherwise command not found error will be raised.

When you called bash file, bash simply treat file as a shell script, read and execute commands from file, then exit. Again, from bash documentation:

If arguments remain after option processing, and neither the -c nor the -s option has been supplied, the first argument is assumed to be the name of a file containing shell commands (see Shell Scripts). When Bash is invoked in this fashion, $0 is set to the name of the file, and the positional parameters are set to the remaining arguments. Bash reads and executes commands from this file, then exits. Bash’s exit status is the exit status of the last command executed in the script. If no commands are executed, the exit status is 0.

So, your understanding is right.

1
  • In Bash's source code, in execute_cmd.c, the function shell_execve has the following comment: /* This file is executable. If it begins with #!, then help out people with losing operating systems. Otherwise, check to see if it is a binary file by seeing if the contents of the first line (or up to 80 characters) are in the ASCII set. If it's a text file, execute the contents as shell commands, otherwise return 126 (EX_BINARY_FILE). */ So basically it looks for a shebang or a magic number signifying an executable throwing an internal error on an executable. Jul 14, 2019 at 20:00
0

Just summary:

  • bash <file> can execute only shell scripts
  • bash -c <file> can execute binaries (e.g. /usr/bin/date, /usr/bin/echo) and executable shell scripts
1
  • 3
    Not exactly. <file> in bash -c <file> needs to be executable. <file> in bash <file> doesn't need to be executable.
    – muru
    Jul 21, 2022 at 4:54

You must log in to answer this question.

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