Шебанг, указывающий на сценарий (также имеющий шебанг), фактически игнорируется - PullRequest
18 голосов
/ 03 апреля 2012

Рассмотрим следующий код:

#!/usr/bin/env python

import sys

print "Hello! I've got %r as input." % sys.stdin.read()

Это chmod +x ed скрипт в /usr/local/bin/my_interpreter. И это:

#!/usr/local/bin/my_interpreter

This is intended to be passed "as is" to python script.

Является chmod +x ed скриптом, который пытается использовать его. Если я echo something | /usr/local/bin/my_interpreter, он работает нормально, но как только я пытаюсь выполнить сценарий выше, он не работает с

/Users/modchan/test_interpreter/foo.bar: line 3: This: command not found

Кажется, что foo.bar молча перенаправляется на bash вместо моего скрипта. Что я делаю неправильно? Как заставить это работать?

Ответы [ 2 ]

13 голосов
/ 03 апреля 2012

Похоже, что Mac OS X требует, чтобы интерпретатор был двоичным, а не другим скриптом.Чтобы заставить его работать, измените интерпретатор второго скрипта на

#!/usr/bin/env /usr/local/bin/my_interpreter

Но у вас здесь есть вторая проблема: содержимое второго скрипта не перейдет к stdin изего интерпретатор, но путь к сценарию будет передан в качестве аргумента командной строки, т. е.

/usr/bin/env /usr/local/bin/my_interpreter /Users/modchan/test_interpreter/foo.bar

. Файл следует читать по имени sys.argv[1], а не из sys.stdin.

4 голосов
/ 03 апреля 2012

Это зависит от загрузчика программы операционной системы, которую вы используете, которую я считаю OS X из ваших тегов. Многие UNIX-подобные операционные системы требуют, чтобы интерпретатор shebang был скомпилированным исполняемым двоичным файлом, а не другим скриптом с другим shebang.

http://en.wikipedia.org/wiki/Shebang_(Unix)

Linux поддерживает это начиная с версии 2.6.27.9, но автор этой статьи предполагает, что, вероятно, не существует Unixen, производного от Berkeley (который, вероятно, будет включать OS X), который бы:

http://www.in -ulm.de / ~ mascheck / различный / притон / # переводчик-скрипт

Один из способов добиться того, чего вы хотите - это что-то вроде этого:

$!/bin/sh
exec /usr/local/bin/my_interpreter <<EOM

... content to be executed ...
EOM

Другой способ был бы примерно таким:

$!/usr/bin/env /usr/local/bin/my_interpreter
... content to be executed ...
...