2013-05-13 10 views
15

Ich bin sehr, sehr neu in der UNIX-Programmierung (läuft auf MacOSX Mountain Lion über Terminal). Ich habe die Grundlagen aus einem Kurs über Bioinformatik und Molekularmethoden gelernt (wir hatten zwei Klassen), wo wir Perl und Python für Datenmanagementzwecke verwenden werden. Wie auch immer, wir wurden damit beauftragt, ein Shell-Skript zu schreiben, um Daten aus einer Gruppe von Dateien zu übernehmen und in eine neue Datei in einem Format zu schreiben, das von einem bestimmten Programm (Migrate-N) gelesen werden kann.UNIX-Neuling: Shell-Skript läuft nicht, Befehl nicht gefunden

Ich habe eine Reihe von Funktionen bekommen, um genau das zu tun, was ich brauche, wenn ich sie in die Befehlszeile eintippe, aber wenn ich sie alle in ein Skript einfüge und versuche, es auszuführen, erhalte ich einen Fehler. Hier sind die Details (I für die Länge entschuldigen):

#! /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 Serie von greps ist nur für jede Site DNA-Sequenzdaten Herausziehen für jeden Locus in neue Textdateien. Die Samples ... txt-Dateien enthalten die Beispiel-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 ausführe.

Die zweite Gruppe von Code erstellt die eigentliche neue Datei, die ich enden muss, die in .mig endet. Die Echolinien sind Daten über Zählungen (Basispaare pro Lokus, Populationen in der Analyse, Stichproben pro Standort usw.), zu denen das Programm Informationen benötigt. Die cat-Zeilen sollen den locus durch Site-Daten, die durch das gesamte grepping unterhalb der in der echo-Zeile festgelegten site-spezifischen Information erzeugt wurden, zusammenstellen. Sie haben zweifellos das Bild.

Zum Erstellen des Shell-Skripts habe ich in Excel gestartet, so kann ich Zellen leicht kopieren, einfügen und als Text mit Tabulatoren speichern, dann die Textdatei in TextWrangler öffnen, um die Tabs vor dem Speichern als zu entfernen. SH-Datei (Zeilenumbrüche: Unix (LF) und Codierung: Unicode (UTF-8)) im selben Verzeichnis wie alle Dateien, die im Skript verwendet werden. Ich habe versucht mit chmod +x FILENAME.sh und chmod u+x FILENAME.sh zu versuchen, um sicherzustellen, dass es ausführbar ist, aber ohne Erfolg. Selbst wenn ich das Skript auf eine einzige Grep-Zeile (mit der #!/Bin/bash-ersten Zeile) reduziere, kann ich es nicht zum Laufen bringen. Der Prozess dauert nur einen Moment, wenn ich es direkt in die Befehlszeile eintippe, da keine dieser Dateien größer als 160 KB und einige deutlich kleiner sind. Dies ist, was ich gebe und was ich bekomme, wenn ich versuche, die Datei (HW ist das richtige Verzeichnis)

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

Ich bin jetzt für zwei Tage in diesem impass zu laufen, so dass jede Eingabe wäre sehr dankbar ! Vielen Dank!!

+3

den Standort von 'MigrateNshell.sh' in Ihrem' PATH' ist? Wenn Sie versuchen, es aus dem aktuellen Verzeichnis auszuführen, versuchen Sie './MigrateNshell.sh'. –

Antwort

1
#! /bin/bash 
    ^--- 

den angezeigten Platz entfernen. Die shebang sollte

#!/bin/bash 
+6

Ein Leerzeichen wird normalerweise nach dem Hashbang toleriert. – chepner

+0

Siehe auch [diese Antwort] (http://stackoverflow.com/a/10197964/3266847). –

28

Aus Sicherheitsgründen werden, wird die Shell nicht das aktuelle Verzeichnis suchen (Standard) für eine ausführbare Datei. Sie müssen spezifisch sein, und sagen bash, dass Ihr Skript im aktuellen Verzeichnis ist (.):

$ ./MigrateNshell.sh 
+0

+1 Ich denke, das wäre die Ursache. – Kent

+2

Sie können auch den Interpreter angeben: 'bash MigrateNshell.sh'. Dies funktioniert auch ohne Ausführungsberechtigungen. – Otaia

-3

Erstens:

chmod 777 ./MigrateNshell.sh 

Dann:

./MigrateNshell.sh 

Oder fügen Sie Ihre Programm zu einem Verzeichnis, das in Ihrer $ PATH-Variable erkannt wird.Beispiel: Path Variable Example die dann erlauben Sie Ihr Programm aufzurufen, ohne ./

+4

Machen Sie das 'chmod 755', nicht' chmod777'. '777' gibt jedem auf dem System Schreibrechte. '755' gibt Ihnen die volle Erlaubnis, aber nur lesen und ausführen für alle anderen. –

1

Unix hat eine Variable namens PATH, die eine Liste von Verzeichnissen, wo Befehle zu finden.

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

Wenn ich einen Befehl foo in der Befehlszeile eingeben, wird meine Shell zuerst sehen, ob es ein ausführbarer Befehl /usr/local/bin/foo. Wenn dies der Fall ist, wird /usr/local/bin/foo ausgeführt. Wenn nicht, wird es sehen, ob es einen ausführbaren Befehl gibt /usr/bin/foo und wenn nicht, wird es sehen, ob /bin/foo existiert, usw., bis es /Users/david/bin/foo erreicht.

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

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

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

können Sie $HOME/.bash_profile oder $HOME/.profile ändern, wenn .bash_profile existiert nicht. Ich tat das, um in /usr/local/bin hinzuzufügen, die ich zuerst in meinem Weg platzierte. Auf diese Weise kann ich die Standardbefehle im Betriebssystem überschreiben. Zum Beispiel habe ich Ant 1.9.1, aber der Mac kam mit Ant 1.8.4. Ich setze meinen ant Befehl in /usr/local/bin, so dass meine Version von ant zuerst ausgeführt wird. Ich fügte auch $HOME/bin zum Ende des PATH für meine eigenen Befehle hinzu. Wenn ich eine Datei wie die, die Sie ausführen möchten, habe, lege ich sie in $ HOME/bin, um sie auszuführen.

14

Ändern Sie die erste Zeile, die folgend wie von Marc B

wies darauf hin,
#!/bin/bash 

markieren Sie dann das Skript als ausführbar und führen Sie es von der Kommandozeile

chmod +x MigrateNshell.sh 
./MigrateNshell.sh 

oder einfach bash von execute Befehlszeile in Ihrem Skript übergeben als Parameter

/bin/bash MigrateNshell.sh 
0

Stellen Sie auch sicher/bin/bash ist der richtige Ort für bash .... Wenn Sie diese Zeile aus einem Beispiel genommen haben, passt sie möglicherweise nicht zu Ihrem bestimmten Server. Wenn Sie einen ungültigen Ort für bash angeben, haben Sie ein Problem.

7

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

$ dos2unix MigrateNshell.sh 

Dies hilft manchmal.

+0

Das hat es für mich gelöst. In diesem Fall konnte ich das Problem sehen (nachdem diese Antwort es vorgeschlagen hatte), indem ich in vi das an jede Zeile angehängte^M bemerkte. Seltsamerweise dachte gvim, es sei schon Unix-Format, also muss es nur eine Zeile gewesen sein, die falsch endete. – lessthanideal

+0

Ich habe überall gesucht vergessen, dass ich die Datei in Windows bearbeitet habe! – Omar

0

Fügen Sie die folgenden Zeilen in Ihrem ein.Profilpfad

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

export PATH 

Nun sollte Ihr Skript arbeiten, ohne ./

Raj Dagla

2

Es gibt ein paar gute Kommentare waren über die shebang line zu Beginn des Skripts hinzufügen. Ich möchte eine Empfehlung hinzufügen, um die env command auch für zusätzliche Portabilität zu verwenden.

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

9

Stellen Sie sicher, dass Sie nicht "PATH" als eine Variable verwenden, die den vorhandenen PATH für Umgebungsvariablen überschreiben wird.

1

Versuchen chmod u+x MigrateNshell.sh