Je suis très, très nouveau dans la programmation UNIX (fonctionnant sous MacOSX Mountain Lion via Terminal). J'ai appris les bases d'un cours de bioinformatique et de méthodes moléculaires (nous avons eu deux cours) où nous utiliserons éventuellement Perl et python à des fins de gestion de données. Quoi qu’il en soit, nous avons été chargés d’écrire un script Shell pour extraire des données d’un groupe de fichiers et les écrire dans un nouveau fichier dans un format pouvant être lu par un programme spécifique (Migrate-N).
J'ai eu un certain nombre de fonctions pour faire exactement ce dont j'ai besoin quand je les tape dans la ligne de commande, mais quand je les rassemble toutes dans un script et que je tente de l'exécuter, j'obtiens une erreur. Voici les détails (je m'excuse pour la longueur):
#! /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
La série de greps extrait simplement les données de séquence d'ADN de chaque site pour chaque locus dans de nouveaux fichiers texte. Les exemples ... Les fichiers txt ont les numéros d'identification des échantillons pour un site, les fichiers .fasta ont les informations de séquence organisées par ID d'échantillons; le grepping fonctionne très bien en ligne de commande si je le lance individuellement.
Le deuxième groupe de code crée le nouveau fichier que je dois terminer, qui se termine par .mig. Les lignes d'écho sont des données sur les comptages (paires de bases par lieu, populations dans l'analyse, échantillons par site, etc.) pour lesquels le programme a besoin d'informations. Les lignes de cat doivent écraser ensemble le locus par les données de site créées par tous les grepings situés sous les informations spécifiques au site dictées dans la ligne d'écho. Vous avez sans doute la photo.
Pour créer le script Shell, je me suis lancé dans Excel afin de pouvoir facilement copier-coller/remplir des cellules, enregistrer en tant que texte délimité par des tabulations, puis ouvrir ce fichier texte dans TextWrangler pour supprimer les onglets avant de les enregistrer sous forme de fichier .sh (Line). breaks: Unix (LF) et Encoding: Unicode (UTF-8)) dans le même répertoire que tous les fichiers utilisés dans le script. J'ai essayé d'utiliser chmod +x FILENAME.sh
et chmod u+x FILENAME.sh
pour essayer de m'assurer qu'il est exécutable, mais en vain. Même si je réduisais le script à une seule ligne grep (avec la première ligne #!/Bin/bash), je ne pouvais pas le faire fonctionner. Le processus ne prend que quelques instants lorsque je le tape directement dans la ligne de commande, car aucun de ces fichiers ne dépasse 160 Ko et certains sont considérablement plus petits. C’est ce que je tape et ce que je reçois quand j’essaie d’exécuter le fichier (HW est le bon répertoire)
localhost:HW Mirel$ MigrateNshell.sh
-bash: MigrateNshell.sh: command not found
Cela fait deux jours que je suis dans cette impasse, toute contribution serait grandement appréciée! Merci!!
Pour des raisons de sécurité, le shell ne cherchera pas dans le répertoire en cours (par défaut) un exécutable. Vous devez être spécifique et indiquer à bash
que votre script se trouve dans le répertoire en cours (.
):
$ ./MigrateNshell.sh
Changer la première ligne comme suit, comme l'a souligné Marc B.
#!/bin/bash
Marquez ensuite le script comme exécutable et exécutez-le à partir de la ligne de commande.
chmod +x MigrateNshell.sh
./MigrateNshell.sh
ou exécutez simplement bash depuis la ligne de commande en transmettant votre script en tant que paramètre
/bin/bash MigrateNshell.sh
Assurez-vous de ne pas utiliser "PATH" en tant que variable, qui remplacera le PATH existant pour les variables d'environnement.
Essayez également de dos2unix
le script Shell, car il comporte parfois des fins de ligne Windows et le shell ne le reconnaît pas.
$ dos2unix MigrateNshell.sh
Cela aide parfois.
Il y a eu quelques bons commentaires sur l'ajout de la ligne Shebang au début du script. Je voudrais ajouter une recommandation pour utiliser la commande env également, pour une portabilité supplémentaire.
Bien que #!/bin/bash
puisse être l'emplacement correct sur votre système, ce n'est pas universel. En outre, il se peut que l'utilisateur ne soit pas préféré bash. #!/usr/bin/env bash
sélectionnera le premier bash trouvé dans le chemin.
Essayez chmod u+x MigrateNshell.sh
#! /bin/bash
^---
supprimez l'espace indiqué. Le Shebang devrait être
#!/bin/bash
Unix a une variable appelée PATH
qui est une liste de répertoires où trouver des commandes.
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/david/bin
Si je tape une commande foo
sur la ligne de commande, mon shell va d'abord voir s'il existe une commande exécutable /usr/local/bin/foo
. Si c'est le cas, il exécutera /usr/local/bin/foo
. Sinon, il verra s'il y a une commande exécutable /usr/bin/foo
et s'il n'y en a pas, il regardera si /bin/foo
existe, etc. jusqu'à ce qu'il atteigne /Users/david/bin/foo
.
S'il ne peut pas trouver une commande foo
dans l'un de ces répertoires, il me dit commande non trouvée .
Je peux gérer ce problème de plusieurs manières:
bash foo
puisque foo
est un script Shell./Users/david/foo
ou $PWD/foo
ou tout simplement ./foo
.$PATH
pour ajouter le répertoire contenant vos commandes au PATH.Vous pouvez modifier $HOME/.bash_profile
ou $HOME/.profile
si .bash_profile
n'existe pas. Je l'ai fait pour ajouter dans /usr/local/bin
que j'ai placé en premier sur mon chemin. De cette façon, je peux remplacer les commandes standard présentes dans le système d'exploitation. Par exemple, j'ai Ant 1.9.1, mais le Mac est venu avec Ant 1.8.4. Je mets ma commande ant
dans /usr/local/bin
afin que ma version de ant
s'exécute en premier. J'ai aussi ajouté $HOME/bin
à la fin du PATH pour mes propres commandes. Si j'avais un fichier comme celui que vous voulez exécuter, je le placerai dans $ HOME/bin pour l'exécuter.
Assurez-vous également que/bin/bash est le bon emplacement pour bash .... si vous prenez cette ligne à partir d'un exemple, elle risque de ne pas correspondre à votre serveur. Si vous spécifiez un emplacement non valide pour bash, vous allez avoir un problème.
Ajouter les lignes ci-dessous dans votre chemin .profile
PATH=$PATH:$HOME/bin:$Dir_where_script_exists
export PATH
Maintenant, votre script devrait fonctionner sans ./
Raj Dagla
Je suis également nouveau dans les scripts Shell, mais j'ai eu le même problème. Assurez-vous qu'à la fin de votre script, vous avez une ligne vide. Sinon, ça ne marchera pas.