Почему «/bin / sh ls» не выполняет ls?

#linux #bash #shell

#linux #bash #оболочка

Вопрос:

Я новичок в shell, извините, если мой вопрос слишком простой.Я использую оболочку Bash, и ниже приведены различные способы запуска команд, которые я пробовал:

 ls               // of course it works :)

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

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

так почему /bin/sh ls не работает? разве когда я использую ls , ls это не исполняемый объект в /bin/ каталоге, поэтому ls он должен быть таким же, как /bin/sh ls , не так ли?

Комментарии:

1. Если задан один позиционный аргумент, этот файл принимается как сценарий оболочки. ls является двоичным файлом и не может использоваться в качестве сценария оболочки.

2. Каково значение переменных «ls» (тип echo $ls )? Это может объяснить поведение, которое вы наблюдаете.

3. /bin/sh ls предполагается, что в вашем рабочем каталоге есть файл с именем ls , и этот файл интерпретируется как сценарий оболочки для sh -shell. Конечно, это чем-то отличается от других случаев. Еще одно отличие: только первая из трех команд вызывает встроенную команду bash ls .

4. @dash-o : Исходя из двух других команд, мы можем предположить, что OP на самом деле не вводил команду $ls , а просто ls ; в противном случае $/bin/sh -c ls это не сработало бы. Я отредактировал публикацию, чтобы устранить путаницу $ .

5. Вы, скорее всего, имели в виду /bin/ls

Ответ №1:

почему /bin / sh ls не работает?

Некоторые соответствующие части из руководства по posix sh:

sh [-abCefhimnuvx] [опция-o]… [ abCefhimnuvx] [ опция o]… [командный файл [аргумент …]]

sh -c [-abCefhimnuvx] [опция-o]… [ abCefhimnuvx] [ опция o]… command_string [имя_команды [аргумент …]]

sh -s [-abCefhimnuvx] [опция-o]… [ abCefhimnuvx] [ опция o]… [аргумент …]

Утилита sh — это интерпретатор командного языка, который должен выполнять команды, считываемые из строки командной строки, стандартного ввода или указанного файла. Приложение должно гарантировать, что выполняемые команды выражены на языке, описанном в Shell Command Language.

-c считывает команды из операнда command_string. […]

-s считывает команды из стандартного ввода.

Если нет операндов и параметр -c не указан, предполагается параметр -s .

command_file Путь к файлу, содержащему команды. [….]

The:

  /bin/sh ls
  

случай попадает в sh command_file случай. Тогда командный файл должен содержать команды оболочки, которые будут интерпретироваться оболочкой. Но ls это исполняемый файл, скорее всего, в исполняемом формате ELF — нигде рядом с командами оболочки, разделенными новой строкой, поэтому оболочка завершается с ошибкой синтаксического анализатора.

разве когда я использую ls, ls не является исполняемым объектом в каталоге /bin /, поэтому ls должен быть таким же, как / bin / sh ls, не так ли?

Нет.

несоответствие при вызове команд разными способами в оболочке?

Нет. Обычно интерпретаторы и компиляторы написаны таким образом, что вы передаете им файлы. Когда вы передаете файл интерпретатору или компилятору, например, когда вы это делаете, gcc file.c вы ожидаете, что file.c файл будет написан на языке программирования C, и он будет скомпилирован в исполняемый файл. Ожидается, что при записи python file — then file будет написано на языке программирования python. Точно так же, когда вы записываете sh file файл, что бы это ни было (в современной операционной системе / POSIX), ожидается, что он будет написан на языке оболочки POSIX sh, содержащем команды оболочки, совместимые с POSIX, а не будет самой командой оболочки.

Ответ №2:

/bin/sh ls заставляет sh открывать ls и читать его построчно для выполнения команд оболочки.

/bin/sh -c ls вызывает sh выполнение командной строки ls .

В некотором смысле, вы можете думать о /bin/sh ls как об эквиваленте

 /bin/sh -c 'while IFS= read -r line; do eval "$line"; done < ls'
  

Ответ №3:

/bin/sh ожидает получить файл сценария в качестве аргумента (когда больше не задано никаких опций), т. Е. текстовый файл, содержащий команду оболочки. ls это двоичный файл, который не может быть прочитан интерпретированным Shell.