Search code examples
linuxbashshell

Why doesn't "/bin/sh ls" execute ls?


I'm new to shell, sorry if my question is too basic.I'm using Bash shell, and below is the different ways of triggering commands I have tried:

ls               // of course it works :)

/bin/sh ls       // error,  ")" unexpected

/bin/sh -c ls    // work just like `ls`

so why /bin/sh ls doesn't work? isn't that when I use ls, ls is an executable object in /bin/ directory, so ls should be the same as /bin/sh ls, shouldn't it?


Solution

  • why /bin/sh ls doesn't work?

    Some relevant parts from posix manual sh:

    sh [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]... [command_file [argument...]]

    sh -c [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]... command_string [command_name [argument...]]

    sh -s [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]... [argument...]

    The sh utility is a command language interpreter that shall execute commands read from a command line string, the standard input, or a specified file. The application shall ensure that the commands to be executed are expressed in the language described in Shell Command Language.

    -c Read commands from the command_string operand. [...]

    -s Read commands from the standard input.

    If there are no operands and the -c option is not specified, the -s option shall be assumed.

    command_file The pathname of a file containing commands. [....]

    The:

     /bin/sh ls
    

    case falls into sh command_file case. Then command file should contain shell commands to be interpreted by the shell. But ls is an executable most probably in ELF executable format - nowhere near a newline separated shell commands - so shell exits with a parser error.

    isn't that when I use ls, ls is an executable object in /bin/ directory, so ls should be the same as /bin/sh ls, shouldn't it?

    No.

    inconsistency when calling commands in different ways in shell?

    No. Usually interpreters and compilers are written in a way that you pass files to them. When you pass a file to an interpreter or compiler, like when you do gcc file.c you expect the file.c to be written in C programming language and it will get compiled into a executable. When you write python file - then file is expected to be written in python programming language. The same way when you write sh file the file, whatever it is, is (on a modern/POSIX operating system) expected to be written in the POSIX sh shell language containing POSIX-compliant shell commands, not to be a shell command itself.