UNIX newbie: shell script не работает, команда не найдена

Я очень, очень новичок в программировании UNIX (работает на MacOSX Mountain Lion через Terminal). Я изучал основы курса биоинформатики и молекулярных методов (у нас было два класса), где мы в конечном итоге будем использовать perl и python для целей управления данными. В любом случае нам было поручено написать оболочку script, чтобы взять данные из группы файлов и записать их в новый файл в формате, который может быть прочитан определенной программой (Migrate-N).

У меня есть ряд функций для выполнения того, что мне нужно независимо, когда я ввожу их в командную строку, но когда я их объединяю в script и пытаюсь запустить, я получаю сообщение об ошибке. Вот подробности (извиняюсь за длину):

#! /bin/bash

grep -f Samples.NFCup.txt locus1.fasta > locus1.NFCup.txt
grep -f Samples.NFCup.txt locus2.fasta > locus2.NFCup.txt
grep -f Samples.NFCup.txt locus3.fasta > locus3.NFCup.txt
grep -f Samples.NFCup.txt locus4.fasta > locus4.NFCup.txt
grep -f Samples.NFCup.txt locus5.fasta > locus5.NFCup.txt
grep -f Samples.Salmon.txt locus1.fasta > locus1.Salmon.txt
grep -f Samples.Salmon.txt locus2.fasta > locus2.Salmon.txt
grep -f Samples.Salmon.txt locus3.fasta > locus3.Salmon.txt
grep -f Samples.Salmon.txt locus4.fasta > locus4.Salmon.txt
grep -f Samples.Salmon.txt locus5.fasta > locus5.Salmon.txt
grep -f Samples.Cascades.txt locus1.fasta > locus1.Cascades.txt
grep -f Samples.Cascades.txt locus2.fasta > locus2.Cascades.txt
grep -f Samples.Cascades.txt locus3.fasta > locus3.Cascades.txt
grep -f Samples.Cascades.txt locus4.fasta > locus4.Cascades.txt
grep -f Samples.Cascades.txt locus5.fasta > locus5.Cascades.txt

echo 3 5 Salex_melanopsis > Smelanopsis.mig
echo 656 708 847 1159 779 >> Smelanopsis.mig
echo 154 124 120 74 126 NFCup >> Smelanopsis.mig
cat locus1.NFCup.txt locus2.NFCup.txt locus3.NFCup.txt locus4.NFCup.txt locus5.NFCup.txt >> Smelanopsis.mig
echo 32 30 30 18 38 Salmon River >> Smelanopsis.mig
cat locus1.Salmon.txt locus2.Salmon.txt locus3.Salmon.txt locus4.Salmon.txt locus5.Salmon.txt >> Smelanopsis.mig
echo 56 52 24 29 48 Cascades >> Smelanopsis.mig
cat locus1.Cascades.txt locus2.Cascades.txt locus3.Cascades.txt locus4.Cascades.txt locus5.Cascades.txt >> Smelanopsis.mig

Серия greps просто вытаскивает данные последовательности ДНК для каждого сайта для каждого локуса в новые текстовые файлы. В образцах... txt есть идентификационные номера образцов для сайта, файлы .fasta имеют информацию о последовательности, организованную с помощью идентификатора образца; grepping отлично работает в командной строке, если я запускаю его по отдельности.

Вторая группа кода создает фактический новый файл, в котором я должен закончить, заканчивающийся на .mig. Эхо-строки - это данные о подсчетах (базовые пары для каждого локуса, популяции в анализе, образцы на сайт и т.д.), О которых программа нуждается в информации. Строки cat заключаются в том, чтобы смять локус по данным сайта, созданным всеми grepping, ниже информации о сайте, продиктованной эхо-линией. Вы, несомненно, получите картину.

Для создания оболочки script я запускаюсь в Excel, поэтому я могу легко копировать/вставлять/автозавершать ячейки, сохраняя в виде текста с разделителями табуляции, а затем открывая этот текстовый файл в TextWrangler, чтобы удалить вкладки перед сохранением в качестве .sh(Разрывы строк: Unix (LF) и Кодировка: Unicode (UTF-8)) в том же каталоге, что и все файлы, используемые в script. Я попытался использовать chmod +x FILENAME.sh и chmod u+x FILENAME.sh, чтобы убедиться, что он является исполняемым, но безрезультатно. Даже если я разрежу script до единственной строки grep (с первой строкой #!/Bin/bash), я не могу заставить ее работать. Процесс занимает всего лишь один момент, когда я ввожу его непосредственно в командную строку, так как ни один из этих файлов не превышает 160 КБ, а некоторые значительно меньше. Это то, что я набираю и что получаю, когда пытаюсь запустить файл (HW - правильный каталог)

localhost:HW Mirel$ MigrateNshell.sh
-bash: MigrateNshell.sh: command not found

Я был на этом тупике уже два дня, поэтому любой вклад был бы очень признателен! Спасибо!!

Ответ 1

Из соображений безопасности оболочка не будет искать текущий каталог (по умолчанию) для исполняемого файла. Вы должны быть конкретными и сообщить bash, что ваш script находится в текущем каталоге (.):

$ ./MigrateNshell.sh

Ответ 2

Измените первую строку на следующую, как указано Marc B

#!/bin/bash 

Затем отметьте script как исполняемый файл и выполните его из командной строки

chmod +x MigrateNshell.sh
./MigrateNshell.sh

или просто выполните bash из командной строки, проходящей в вашем script в качестве параметра

/bin/bash MigrateNshell.sh

Ответ 3

Убедитесь, что вы не используете "PATH" в качестве переменной, которая переопределит существующие переменные PATH для переменных среды.

Ответ 4

Также попробуйте dos2unix оболочку script, потому что иногда она имеет окончания строки Windows, и оболочка ее не распознает.

$ dos2unix MigrateNshell.sh

Иногда это помогает.

Ответ 5

Было несколько хороших комментариев о добавлении env, для дополнительной портативность.

Хотя #!/bin/bash может быть правильным местом в вашей системе, это не универсально. Кроме того, это может быть не предпочтительнее пользователя bash. #!/usr/bin/env bash выберет первый bash, найденный в пути.

Ответ 6

#! /bin/bash
  ^---

удалите указанное пространство. Shebang должен быть

#!/bin/bash

Ответ 7

Unix имеет переменную с именем PATH, которая представляет собой список каталогов, где можно найти команды.

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/david/bin

Если я введу команду foo в командной строке, моя оболочка сначала увидит, есть ли исполняемая команда /usr/local/bin/foo. Если есть, он выполнит /usr/local/bin/foo. Если нет, он увидит, есть ли исполняемая команда /usr/bin/foo, а если нет, она увидит, существует ли /bin/foo и т.д., Пока не дойдет до /Users/david/bin/foo.

Если он не может найти команду foo в любом из этих каталогов, это говорит мне, что команда не найдена.

Есть несколько способов решить эту проблему:

  • Используйте команду bash foo, так как foo - это оболочка script.
  • Включите имя каталога, когда вы выполните команду, например /Users/david/foo или $PWD/foo, или просто ./foo.
  • Измените переменную $PATH, чтобы добавить каталог, содержащий ваши команды, в PATH.

Вы можете изменить $HOME/.bash_profile или $HOME/.profile, если .bash_profile не существует. Я сделал это, чтобы добавить в /usr/local/bin, который я разместил первым на своем пути. Таким образом, я могу переопределить стандартные команды, которые находятся в ОС. Например, у меня есть Ant 1.9.1, но Mac пришел с Ant 1.8.4. Я поместил свою команду ant в /usr/local/bin, поэтому первая версия ant будет выполнена первой. Я также добавил $HOME/bin в конец PATH для своих собственных команд. Если бы у меня был файл, подобный тому, который вы хотите выполнить, я поместил его в $HOME/bin для его выполнения.

Ответ 8

Также убедитесь, что /bin/ bash является подходящим местом для bash.... если вы взяли эту строку из примера где-то, она может не соответствовать вашему конкретному серверу. Если вы указали неверное местоположение для bash, у вас возникнет проблема.

Ответ 9

Добавьте ниже строки в свой путь .profile

PATH=$PATH:$HOME/bin:$Dir_where_script_exists

export PATH

Теперь ваш script должен работать без ./

Радж Дагла

Ответ 10

Попробуйте chmod u+x MigrateNshell.sh

Ответ 11

Во-первых:

chmod 777 ./MigrateNshell.sh

Тогда:

./MigrateNshell.sh

Или добавьте свою программу в каталог, распознанный в переменной $PATH. Пример: Пример переменной пути Затем вы сможете называть свою программу без ./