Если скрипт, скопированный из Windows, выглядит нормально, но macOS выдает ошибку «bad interpreter» или ведет себя так, будто в командах есть лишний символ, проверьте окончания строк Windows CRLF. Инструменты командной строки macOS ожидают LF. Вы можете подтвердить тип файла, преобразовать копию с помощью встроенных в macOS средств, а затем снова запустить исправленный скрипт.
Почему окончания строк ломают скрипты в macOS
Окончание строки — это символ (или пара символов), обозначающий конец строки текста. Инструменты командной строки macOS используют LF (\n); Windows обычно использует CRLF (\r\n). При использовании CRLF символ возврата каретки может оставаться прикрепленным к строке, когда ее считывает команда Unix. В документации Apple отмечается, что этот дополнительный символ может вызывать непредвиденное поведение инструментов командной строки и скриптов. Руководство Apple по написанию shell-скриптов
К типичным признакам относятся ошибка /bin/bash^M: bad interpreter, сообщение command-not-found, которое, похоже, содержит замыкающий \r, или сбой синтаксического анализа, даже если визуально скрипт выглядит правильным. Эти симптомы могут иметь и другие причины; проверка файла — полезный первый шаг, но сам по себе еще не доказательство.
Проверка формата окончаний строк скрипта
Откройте Терминал, перейдите в папку, содержащую скрипт, и проверьте его с помощью file. Заключайте имя файла в кавычки, чтобы пробелы и метасимволы оболочки воспринимались буквально:
cd "$HOME/Downloads"
file "my script.sh"
Если в выводе указано, что файл имеет терминаторы строк CRLF, это подтверждает диагноз. Если сообщается о LF, причина может быть не в окончаниях строк. Описание команды file в macOS может различаться, а смешанные окончания строк могут быть сформулированы не совсем понятно, поэтому также обращайте внимание на текст ошибки и контекст исходного кода скрипта. Чтобы просмотреть байты конкретной строки, в macOS также есть утилита od; например:
od -An -tx1 -c "my script.sh" | head
Последовательность 0d 0a обозначает CRLF; 0a отдельно — это LF. Не считайте возврат каретки в других местах файла окончанием строки, не проверив его позицию.
Преобразование CRLF в LF без перезаписи оригинала
В руководстве Apple по macOS указано, что утилита dos2unix не входит в состав macOS, и вместо нее рекомендуется использовать tr или sed. Для скрипта с CRLF удалите символы возврата каретки, сохранив результат в отдельный файл и оставив оригинал в качестве резервной копии:
cp -p "my script.sh" "my script.sh.bak"
tr -d '\r' < "my script.sh" > "my script.lf.sh"
file "my script.lf.sh"
Это подходит в тех случаях, когда нежелательные возвраты каретки являются символами окончания строк Windows. Команда удаляет каждый байт CR в файле, поэтому избегайте ее использования, если файл намеренно содержит возвраты каретки как данные. Вывод в отдельный файл также защищает от усечения исходных данных: прямое перенаправление в тот же самый файл может стереть его до завершения преобразования.
Проверьте новый файл, прежде чем что-либо заменять. Если содержимое выглядит правильно и file сообщает об окончаниях LF, попробуйте запустить его с помощью предназначенного для него интерпретатора. Для скрипта Bash, например:
bash "my script.lf.sh"
Запуск через bash не требует бита разрешения на выполнение или работающего шебанга. Если вам нужно запускать его напрямую как ./my script.lf.sh, сделайте его исполняемым и убедитесь, что в его первой строке указан доступный интерпретатор, например #!/bin/bash:
chmod +x "my script.lf.sh"
"./my script.lf.sh"
Проверив исправленный файл, вы можете заменить им оригинал в Finder или Терминале. Сохраняйте копию .bak до тех пор, пока скрипт не заработает должным образом. Если скрипт является частью общего проекта, внесите аналогичное исправление окончаний строк в настройках исходного редактора или в рабочем процессе репозитория, чтобы проблема не вернулась при повторном сохранении файла.
Если ошибка сохраняется
Если file сразу показал LF или преобразование не устранило сбой, внимательно прочтите точный текст ошибки и проверьте интерпретатор, указанный в первой строке. Отсутствующий интерпретатор, неверный путь, синтаксическая ошибка или отсутствие прав на выполнение могут вызывать похожие проблемы. Скрипт также может зависеть от команд или функций оболочки, которые недоступны в указанном интерпретаторе.
Программа TextEdit может открывать и сохранять текстовые документы, однако в официальном руководстве Apple по TextEdit нет описания средства выбора окончаний строк. Для данного исправления используйте описанное выше преобразование в Терминале или редактор кода, который явно показывает и позволяет изменять окончания строк; после этого обязательно проверьте сохраненный файл. Руководство по TextEdit от Apple
Оптимальная последовательность действий: определить формат файла, сохранить резервную копию, конвертировать только при наличии CRLF и перезапустить скрипт с использованием нужного интерпретатора. Это позволит устранить проблему точечно в данном файле, не затрагивая другие скрипты.
Источники
Designing Scripts for Cross-Platform Deployment — Apple Developer
Создание, открытие и преобразование документов в TextEdit на Mac — Служба поддержки Apple