#! / bin / bash - нет такого файла или каталога

70

Я создал скрипт bash, но когда я пытаюсь его выполнить, я получаю

#!/bin/bash no such file or directory

Мне нужно запустить команду: bash script.shчтобы она работала.

Как я могу это исправить?

Николя де Фонтене
источник
У меня есть эта проблема сейчас под Cygwin с помощью сценария, который я мог поклясться, уже работает без проблем. Я проверил все ответы, но ни один из них не подходит. В других вопросах и ответах также упоминались проблемы с 32/64 битами, но для сценариев оболочки это можно исключить, верно?
января
Выяснили причину, добавили подробности в новом ответе unix.stackexchange.com/a/450389/62636 на случай, если кто-то тоже использовал #!/usr/bin/env bashвместо этого #!/bin/bashи тоже ищет здесь ...
Ян

Ответы:

100

Сообщение такого рода обычно происходит из-за фиктивной строки shebang, либо из-за дополнительного возврата каретки в конце первой строки, либо из спецификации в начале.

Бегать:

$ head -1 yourscript | od -c

и посмотрим, чем это закончится.

Это не верно:

0000000   #   !   /   b   i   n   /   b   a   s   h  \r  \n

Это тоже неправильно:

0000000 357 273 277   #   !   /   b   i   n   /   b   a   s   h  \n

Это верно:

0000000   #   !   /   b   i   n   /   b   a   s   h  \n

Использование dos2unix(или sed, tr, awk, perl, python...) , чтобы исправить сценарий , если это вопрос.

Вот тот, который удалит как спецификацию, так и хвостовые CR:

sed -i '1s/^.*#//;s/\r$//' brokenScript


Обратите внимание, что оболочка, которую вы используете для запуска скрипта, немного повлияет на отображаемые сообщения об ошибках.

Вот три сценария, которые просто показывают их имя ( echo $0) и имеют следующие соответствующие строки:

correctScript:

0000000   #   !   /   b   i   n   /   b   a   s   h  \n

scriptWithBom:

0000000 357 273 277   #   !   /   b   i   n   /   b   a   s   h  \n

scriptWithCRLF:

0000000   #   !   /   b   i   n   /   b   a   s   h  \r  \n

Под bash их запуск покажет эти сообщения:

$ ./correctScript
./correctScript
$ ./scriptWithCRLF
bash: ./scriptWithCRLF: /bin/bash^M: bad interpreter: No such file or directory
$ ./scriptWithBom
./scriptWithBom: line 1: #!/bin/bash: No such file or directory
./scriptWithBom

Запуск фиктивных вызовов путем явного вызова интерпретатора позволяет запускать скрипт CRLF без каких-либо проблем:

$ bash ./scriptWithCRLF
./scriptWithCRLF
$ bash ./scriptWithBom
./scriptWithBom: line 1: #!/bin/bash: No such file or directory
./scriptWithBom

Вот поведение, наблюдаемое под ksh:

$ ./scriptWithCRLF
ksh: ./scriptWithCRLF: not found [No such file or directory]
$ ./scriptWithBom
./scriptWithBom[1]: #!/bin/bash: not found [No such file or directory]
./scriptWithBom

и под dash:

$ ./scriptWithCRLF
dash: 2: ./scriptWithCRLF: not found
$ ./scriptWithBom
./scriptWithBom: 1: ./scriptWithBom: #!/bin/bash: not found
./scriptWithBom
jlliagre
источник
2
Еще один способ раскрытия, если это проблема hexdump -C yourscript | head -n 1. Я все еще использовал бы, dos2unix yourscriptчтобы исправить это.
Кевин М.
Да, это может быть очень хорошо. Я редактировал в Windows. Вещи для чаевых.
Николя де Фонтене
1
Если бы это была проблема CRLF, вы бы не увидели #!/bin/bash no such file or directoryсообщение об ошибке, поскольку нет никаких причин, по которым что-либо пыталось бы выполнить или открыть #!/bin/bash. Это /bin/bash<CR>то, что будет выполнено.
Стефан Шазелас
1
@StephaneChazelas Поскольку dos2unix устранил проблему, нет сомнений, что это не проблема CRLF. Сообщение об ошибке, вероятно, было просто неточно
записано
6
dos2unixтакже удаляет спецификацию UTF-8. Спецификация UTF-8 могла бы объяснить сообщение об ошибке.
Стефан Шазелас
17

Это также может быть вызвано спецификацией в сценарии UTF-8. Если вы создаете сценарий в Windows, иногда вы получаете немного мусора в начале файла.

teknopaul
источник
Спецификация может быть легко удалена с помощью awk, как в stackoverflow.com/questions/1068650/…
pauxu
1
Обратите внимание, что Visual Studio для Mac вставит спецификацию.
яснее
9

На самом деле, правильный сценарий для bash-скриптов таков:

#!/usr/bin/env bash

Потому что в FreeBSD Bash находится в /usr/local/bin/bash

moebius_eye
источник
13
«Право» - трудное слово для использования в таких случаях. Возможно, лучшая фраза будет "менее подвержена ошибкам".
HalosGhost
1
Это тоже ужасно; предположение, что / usr существует, является плохим IMO. Хайку, например, не имеет / usr.
Джессика
9

Вы можете использовать vi, чтобы исправить обе проблемы, если они существуют:

vi <your_file>
:set ff=unix
:set nobomb
:wq
cwash
источник
Ответы должны быть максимально автономными. Вопрос не затрагивает две проблемы; если вы собираетесь опираться на другие ответы, вы должны хотя бы сказать, что они есть. А еще лучше, вы должны объяснить, как это отвечает на вопрос.
G-Man
Очень быстро исправить, не загружая больше инструментов Windows, спасибо!
SteamPowered
1
@ G-Man Другие ответы уже упоминают об этом гораздо лучше, чем я хотел бы вдаваться. Не нужно повторять, но если это не до боли очевидно, у вас может быть конец строки WIndows и скрытый символ спецификации Windows. Я думаю, что многие люди, которые просматривают ответы, ценят краткость, а не самодостаточность, особенно когда в других ответах гораздо больше деталей.
Cwash
4

Если у вас нет dos2unix, это способ исправить эту проблему.

cp script _p4 && tr -d '\r' < _p4 > script && rm _p4
cokedude
источник
3

Порядок следования байтов (BOM)

Это может быть вызвано спецификацией. Из Википедии, спецификация

Метка порядка байтов (BOM) - это символ Unicode, метка порядка байтов U + FEFF (BOM), чье появление в виде магического числа в начале текстового потока может сигнализировать о нескольких вещах программе, потребляющей текст

К сожалению, это ничего не сигнализирует ядру Linux, которое обрабатывает строку she-bang. Вы можете подтвердить, что у вас есть спецификация, используя file,

file /tmp/foo 
/tmp/foo: UTF-8 Unicode (with BOM) text

Или вы можете зашифровать первые несколько символов и посмотреть, соответствуют ли они любому из символов спецификации вручную

Вы можете лишить персонажей спецификации, как только узнаете их,

sed -i '1 s/^\xef\xbb\xbf//' *.txt
Фабьен Хаддади
источник
0

Я столкнулся с проблемой, случайно добавив неверный исполняемый файл bash к PATHи потому, что в моем скрипте #!/usr/bin/env bashбыл использован более гибкий shebang (возьмите первый исполняемый файл bash по пути).

command -v bash
/cygdrive/c/Program Files/Git/bin//bash

Я установил GIT для Windows, чтобы работать cygwinвместе с Windows GIT GUI (не работал с родным git cygwin ...). Я решил это сейчас, переключившись на #!/bin/bashsheband и удалив GIT для Windows PATH.

январь
источник
-3

Пытаться #!/bin/bash

Вторая вещь: find / -name bash
третья вещь:ls -al /bin/bash

Себастьян Сзары
источник
Или просто which bash. Мы знаем, что он находит, потому что работает с bash script.sh.
Кевин
Правда. И, как уже упоминалось, есть гораздо более переносимый метод / usr / bin / env, чтобы программа могла найти bash (или другой интерпретатор) для вас. Не нужно жестко кодировать тьфу.
Хеннес