it-swarm.com.de

Shell-Skript läuft nicht, Befehl nicht gefunden

Ich bin sehr, sehr neu in der UNIX-Programmierung (lauffähig auf MacOSX Mountain Lion via Terminal). Ich habe die Grundlagen aus einem Kurs für Bioinformatik und molekulare Methoden (wir hatten zwei Klassen) gelernt, in dem wir Perl und Python für die Datenverwaltung verwenden werden. Wie auch immer, wir wurden mit dem Schreiben eines Shell-Skripts beauftragt, um Daten aus einer Gruppe von Dateien in eine neue Datei in einem Format zu schreiben, das von einem bestimmten Programm (Migrate-N) gelesen werden kann. 

Ich habe eine Reihe von Funktionen bekommen, um genau das zu tun, was ich unabhängig brauche, wenn ich sie in die Befehlszeile eingebe. Wenn ich sie jedoch alle in einem Skript zusammenstelle und versuche, es auszuführen, erhalte ich eine Fehlermeldung. Hier sind die Details (ich entschuldige mich für die Länge):

#! /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

Die Greps-Serie zieht nur DNA-Sequenzdaten für jeden Standort für jeden Ort in neue Textdateien. Die Samples ...-TXT-Dateien enthalten die Sample-ID-Nummern für eine Site. Die .fasta-Dateien enthalten die Sequenzinformationen nach Sample-ID. Das Grepping funktioniert gut in der Befehlszeile, wenn ich es einzeln starte. 

Die zweite Gruppe von Code erstellt die eigentliche neue Datei, die am Ende benötigt wird. Sie endet in .mig. Die Echolinien sind Daten zu Zählungen (Basenpaare pro Locus, Populationen in der Analyse, Proben pro Standort usw.), zu denen das Programm Informationen benötigt. Die Katzenzeilen mischen den Ort nach Standortdaten, die von allen Begrüßungen unterhalb der standortspezifischen Informationen erstellt werden, die in der Echozeile vorgegeben sind. Sie erhalten zweifellos das Bild.

Zum Erstellen des Shell-Skripts habe ich in Excel angefangen, so dass ich die Zellen leicht kopieren und einfügen/automatisch ausfüllen kann. Als Text mit Tabulatortrennzeichen speichern und dann die Textdatei in TextWrangler öffnen, um die Tabulatoren zu entfernen, bevor sie als .sh-Datei (Zeile bricht: Unix (LF) und Encoding: Unicode (UTF-8)) im selben Verzeichnis wie alle im Skript verwendeten Dateien. Ich habe versucht, mit chmod +x FILENAME.sh und chmod u+x FILENAME.sh zu versuchen, sicherzustellen, dass es ausführbar ist, jedoch ohne Erfolg. Selbst wenn ich das Skript auf eine einzige grep-Zeile (mit der ersten Zeile #!/Bin/bash) reduziere, kann ich es nicht schaffen. Der Vorgang dauert nur einen Moment, wenn ich ihn direkt in die Befehlszeile eingebe, da keine dieser Dateien größer als 160 KB ist und einige erheblich kleiner sind. Dies ist, was ich eingebe und wenn ich versuche, die Datei auszuführen (HW ist das richtige Verzeichnis)

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

Ich bin jetzt seit zwei Tagen bei diesem Unpass dabei, daher wäre jede Eingabe sehr dankbar! Vielen Dank!!

21
ChickadeeChick

Aus Sicherheitsgründen durchsucht die Shell das aktuelle Verzeichnis (standardmäßig) nicht nach einer ausführbaren Datei. Sie müssen genau sein und bash mitteilen, dass sich Ihr Skript im aktuellen Verzeichnis (.) befindet:

$ ./MigrateNshell.sh
32
chepner

Ändern Sie die erste Zeile wie folgt von Marc B

#!/bin/bash 

Markieren Sie dann das Skript als ausführbar und führen Sie es über die Befehlszeile aus

chmod +x MigrateNshell.sh
./MigrateNshell.sh

oder führen Sie einfach bash von der Kommandozeile aus und übergeben Sie Ihr Skript als Parameter

/bin/bash MigrateNshell.sh
17
Ryan Williams

Stellen Sie sicher, dass Sie "PATH" nicht als Variable verwenden. Dadurch wird der vorhandene PATH für Umgebungsvariablen überschrieben.

9
janhavi

Versuchen Sie auch, das Shell-Skript zu dos2unix zu benennen, da es manchmal Windows-Zeilenenden hat und die Shell es nicht erkennt.

$ dos2unix MigrateNshell.sh

Das hilft manchmal.

7
Adolfo

Es gab einige gute Kommentare zum Hinzufügen der Shebang-Zeile am Anfang des Skripts. Ich möchte eine Empfehlung hinzufügen, um den env-Befehl zu verwenden, um die Portabilität zu erhöhen.

Während #!/bin/bash möglicherweise der richtige Ort auf Ihrem System ist, ist dies nicht universell. Darüber hinaus ist dies möglicherweise nicht die bevorzugt bash des Benutzers. #!/usr/bin/env bash wählt die erste im Pfad gefundene Bash aus.

2
broadmonkey

chmod u+x MigrateNshell.sh ausprobieren

2
Aminah Nuraini
#! /bin/bash
  ^---

entfernen Sie den angegebenen Platz. Der Shebang sollte sein

#!/bin/bash
1
Marc B

Unix hat eine Variable namens PATH, die eine Liste von Verzeichnissen ist, in denen Befehle gesucht werden.

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

Wenn ich in der Befehlszeile einen Befehl foo eingebe, wird meine Shell zuerst sehen, ob es einen ausführbaren Befehl /usr/local/bin/foo gibt. Wenn ja, wird /usr/local/bin/foo ausgeführt. Wenn nicht, wird festgestellt, ob es einen ausführbaren Befehl /usr/bin/foo gibt, und wenn nicht, prüft es, ob /bin/foo vorhanden ist usw., bis es zu /Users/david/bin/foo gelangt.

Wenn es in keinem dieser Verzeichnisse einen Befehl foo findet, sagen Sie mir Befehl nicht gefunden .

Es gibt mehrere Möglichkeiten, wie ich mit diesem Problem umgehen kann:

  • Verwenden Sie den Befehlbash foo, da foo ein Shell-Skript ist.
  • Geben Sie den Verzeichnisnamen an, wenn Sie den Befehl ausführen, wie /Users/david/foo oder $PWD/foo oder einfach nur ./foo.
  • Ändern Sie Ihre $PATH-Variable, um das Verzeichnis, das Ihre Befehle enthält, zum PATH hinzuzufügen.

Sie können $HOME/.bash_profile oder $HOME/.profile ändern, wenn .bash_profile nicht vorhanden ist. Ich habe das getan, um /usr/local/bin hinzuzufügen, den ich zuerst in meinen Pfad eingefügt habe. Auf diese Weise kann ich die Standardbefehle im Betriebssystem überschreiben. Ich habe zum Beispiel Ant 1.9.1, aber der Mac kam mit Ant 1.8.4. Ich habe meinen ant-Befehl in /usr/local/bin gestellt, so dass meine Version von ant zuerst ausgeführt wird. Ich habe auch $HOME/bin am Ende des PATH für meine eigenen Befehle hinzugefügt. Wenn ich eine Datei wie die, die Sie ausführen möchten, hatte, platziere ich sie in $ HOME/bin, um sie auszuführen.

1
David W.

Stellen Sie außerdem sicher, dass/bin/bash der richtige Ort für bash ist. Wenn Sie diese Zeile aus einem Beispiel entnommen haben, stimmt sie möglicherweise nicht mit Ihrem Server überein. Wenn Sie einen ungültigen Speicherort für Bash angeben, wird ein Problem auftreten.

0
James Gawron

Fügen Sie unten in Ihrem .profile-Pfad Zeilen hinzu

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

export PATH

Jetzt sollte Ihr Skript ohne ./ funktionieren.

Raj Dagla

0
Raj Dagla

Ich bin auch neu im Shell-Scripting, aber ich hatte das gleiche Problem. Stellen Sie sicher, dass Sie am Ende Ihres Skripts eine Leerzeile haben. Sonst funktioniert es nicht.

0
A Smith