Erreur de syntaxe Bash: fin de fichier inattendue

98

Pardonnez-moi pour ceci est un script très simple dans Bash. Voici le code:

#!/bin/bash
# june 2011

if [ $# -lt 3 -o $# -gt 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

après avoir exécuté sh file.sh:

erreur de syntaxe: fin de fichier inattendue

Markcruz
la source

Réponses:

137

Je pense que file.sh est avec des terminateurs de ligne CRLF.

courir

dos2unix file.sh

alors le problème sera résolu.

Vous pouvez installer dos2unix dans ubuntu avec ceci:

sudo apt-get install dos2unix
clyfish
la source
Quelle est la raison de ce problème? Je travaille généralement sous Windows mais j'ai besoin de transférer des scripts sur des systèmes Unix.
CMCDragonkai
La nouvelle ligne dans Windows est "\ r \ n", tandis que sous Linux est "\ n".
clyfish
8
@KeesdeKooter Je ne dirais pas simplement parce que quelque chose n'a pas fonctionné pour vous que vous devriez voter contre, clairement cela a fonctionné pour les 28 votes positifs. Un simple cela n'a pas fonctionné pour moi suffit. C'est pourquoi SO autorise plusieurs réponses à une question car il peut y avoir plusieurs solutions à un problème.
Jeff Wilbert
2
L'utilisation de l'éditeur notepad ++ Edit> EOL Conversion> Old Mac Format a résolu le problème pour moi.
raktale
Si vous pouvez modifier votre fichier bash avec Notepad ++. Allez dans Edition-> Conversion EOL-> Macintosh (CR). Changez-le en Macintosh (CR) même si vous utilisez Windows OS.
Juniar
127

Une autre chose à vérifier (vient de m'arriver):

  • terminer le corps des fonctions sur une seule ligne par un point-virgule

C'est-à-dire que cet extrait de code innocent provoquera la même erreur:

die () { test -n "$@" && echo "$@"; exit 1 }

Pour rendre l'analyseur muet heureux:

die () { test -n "$@" && echo "$@"; exit 1; }
ulidtko
la source
3
+1 S'applique également aux extraits de code entre crochets comme ceci: [["$ #" == 1]] && [["$ arg" == [1,2,3,4]]] && printf "% s \ n "" bla "|| {printf "% s \ n" "blabla"; usage; } ............ Notez ce point-virgule à l'intérieur des crochets ondulés, juste après avoir appelé une fonction définie précédemment «usage». Oublier cela vous obtiendra la même erreur de syntaxe: eof inattendu.
Cbhihe
Vous avez réussi. En fait, la chose la plus simple est que l' ;instruction Every doit se terminer par de ;sorte que, à la fin, par exemple: if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash fiproduira cette erreur, alors que if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash; fi;ne remarquera pas les petits points-virgules à la fin, c'est-à-dire: après .bashet fi.
Emmanuel Mahuni
1
J'avais ceci dans un script partagé avec moi par un zshutilisateur. Le premier fonctionne dans zshmais pas dans shni bash. J'aimerais être 4 personnes pour pouvoir donner 4 votes positifs
Davos
41

Je viens également de recevoir ce message d'erreur en utilisant la mauvaise syntaxe dans une ifclause

  • else if (erreur de syntaxe: fin de fichier inattendue)
  • elif (syntaxe correcte)

Je l'ai débogué en commentant des bits jusqu'à ce que cela fonctionne

Marengaz
la source
Merci beaucoup ... quelqu'un donne une médaille à ce gars
Happiehappie
16

une clause if => fi non fermée le soulèvera également

astuce: utilisez trap pour déboguer, si votre script est énorme ...

par exemple

set -x
trap read debug
theRiley
la source
1
J'ai exactement oublié le "fi"! Merci :) Si vous pouviez, pour le bénéfice de tout le monde, élaborez un peu votre astuce d'utilisation de trap.
Carles Alcolea
3
désolé pour le retard, mon ami. 'la commande' trap 'est un moyen de déboguer vos scripts en cassant essentiellement après chaque ligne. une discussion plus complète est ici: stackoverflow.com/questions/9080431/…
theRiley
1
Cela a été utile merci beaucoup. Notez que l' unexpected end of fileerreur se produira dès que le fiest frappé.
Stephane B.
8

J'ai eu cette réponse de ce problème similaire sur StackOverflow

Ouvrez le fichier dans Vim et essayez

:set fileformat=unix

Convertissez les fins de ligne eh en fins unix et voyez si cela résout le problème. Si vous modifiez dans Vim, entrez la commande: set fileformat = unix et enregistrez le fichier. Plusieurs autres éditeurs ont la possibilité de convertir les fins de ligne, comme Notepad ++ ou Atom

Merci @lemongrassnginger

Jay Killeen
la source
Ce ne sont que des moyens alternatifs de faire ce dos2unixque la réponse acceptée conseille.
ulidtko
7

sur cygwin j'avais besoin: -

 export SHELLOPTS
 set -o igncr

dans .bash_profile. De cette façon, je n'ai pas besoin d'exécuter unix2dos

zzapper
la source
6

J'ai donc trouvé cet article et les réponses ne m'ont pas aidé, mais j'ai pu comprendre pourquoi cela m'a donné l'erreur. J'ai eu un

cat > temp.txt < EOF
some content
EOF

Le problème était que j'avais copié le code ci-dessus pour être dans une fonction et que j'avais par inadvertance tabulé le code. Il faut s'assurer que le dernier EOF n'est pas tabulé.

Rafael Urena
la source
1
C'était exactement mon cas. J'avais mis en EOFretrait de quatre espaces et bash ne l'avait pas analysé à cause de cela. La suppression des espaces a résolu le problème.
aexl
5

J'ai eu le problème quand j'ai écrit la déclaration "if - fi" sur une ligne:

if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash fi

Écrire multiligne a résolu mon problème:

if [ -f ~/.git-completion.bash ]; then 
    . ~/.git-completion.bash
 fi
Sergey
la source
3

Cela se passait pour moi lorsque j'essayais d'appeler une fonction en utilisant des parens, par exemple

run() {
  echo hello
}

run()

devrait être:

run() {
  echo hello
}

run
Christian Scott
la source
2

POUR LES FENÊTRES:

Dans mon cas, je travaillais sur le système d'exploitation Windows et j'ai eu la même erreur lors de l'exécution d'autoconf.

  • J'ouvre simplement le fichier configure.ac avec mon IDE NOTEPAD ++ .
  • Ensuite, j'ai converti le fichier avec la conversion EOL en Windows (CR LF) comme suit:

    EDIT -> CONVERSION EOL -> WINDOWS (CR LF)

Juniar
la source
1

J'ai pu couper et coller votre code dans un fichier et il a fonctionné correctement. Si vous l'exécutez comme ceci, cela devrait fonctionner:

Votre "file.sh":

#!/bin/bash
# june 2011

if [ $# -lt 3 -o $# -gt 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

La commande:

$ ./file.sh arg1 arg2 arg3

Notez que "file.sh" doit être exécutable:

$ chmod +x file.sh

Vous obtenez peut-être cette erreur en raison de la façon dont vous effectuez les entrées (avec un tuyau, une carotte, etc.). Vous pouvez également essayer de diviser la condition en deux:

if [ $# -lt 3 ] || [ $# -gt 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

Ou, puisque vous utilisez bash, vous pouvez utiliser la syntaxe intégrée:

if [[ $# -lt 3 || $# -gt 3 ]]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

Et, enfin, vous pouvez bien sûr simplement vérifier si 3 arguments ont été donnés (nettoyer, maintient la compatibilité du shell POSIX):

if [ $# -ne 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi
aaronstacy
la source
j'ai toujours la même erreur. Je ne sais pas exactement où le code va mal
markcruz
bizarre, j'ai coupé et collé votre code et cela a fonctionné comme prévu. y avait-il plus de sortie d'erreur? beaucoup de temps bash listera un numéro de ligne. aussi, quel système utilisez-vous? (Linux, MacOS, BSD, distribution, etc.)
aaronstacy
0

Je viens de copier-coller votre exemple dans un fichier; il a bien fonctionné sous bash. Je n'y vois aucun problème.

Pour faire bonne mesure, vous voudrez peut-être vous assurer qu'il se termine par une nouvelle ligne, bien que bash ne devrait pas s'en soucier. (Il fonctionne pour moi à la fois avec et sans la dernière ligne.)

Vous verrez parfois des erreurs étranges si vous avez accidentellement incorporé un caractère de contrôle dans le fichier. Puisqu'il s'agit d'un script court, essayez de créer un nouveau script en le collant à partir de votre question ici sur StackOverflow, ou en le retapant simplement.

Quelle version de bash utilisez-vous? ( bash --version)

Bonne chance!

Adam Liss
la source
0

Assurez-vous que le nom du répertoire dans lequel se trouve le fichier .sh ne comporte pas de caractère espace. Par exemple: dites que si c'est dans un dossier appelé «Nouveau dossier», vous êtes obligé de rencontrer l'erreur que vous avez citée. Au lieu de cela, nommez-le simplement «New_Folder». J'espère que ça aide.


la source
0

Apparemment, certaines versions du shell peuvent également émettre ce message lorsque la dernière ligne de votre script n'a pas de nouvelle ligne.

tripleee
la source
0

Dans Ubuntu:

$ gedit ~/.profile

Ensuite, File -> Save aset réglez end linesurUnix/Linux

Bec
la source
0

Je sais que je suis trop tard à la fête. J'espère que cela peut aider quelqu'un.

Vérifiez votre fichier .bashrc. Peut-être le renommer ou le déplacer.

Discussion ici: Impossible de trouver un script bash simple

viggy28
la source
0

Pour les personnes utilisant MacOS:

Si vous avez reçu un fichier au format Windows et que vous vouliez exécuter sur MacOS et que vous voyiez cette erreur, exécutez ces commandes.

brew install dos2unix
sh <file.sh>
vmorusu
la source
0

Manquer une accolade fermante sur une définition de fonction provoquera cette erreur comme je viens de le découvrir.

function whoIsAnIidiot() {
    echo "you are for forgetting the closing brace just below this line !"

Ce qui bien sûr devrait être comme ça ...

function whoIsAnIidiot() {
    echo "not you for sure"
}
Mike
la source
0

Dans mon cas, il y a un redondant \ dans ce qui suit:

function foo() {
    python tools/run_net.py \
                           --cfg configs/Kinetics/X3D_8x8_R50.yaml \
                           NUM_GPUS 1 \
                           TRAIN.BATCH_SIZE 8 \
                           SOLVER.BASE_LR 0.0125 \
                           DATA.PATH_TO_DATA_DIR ./afs/kinetics400 \
                           DATA.PATH_PREFIX  ./afs/kinetics400  \  # Error
}

Il n'y a pas un \à la fin deDATA.PATH_PREFIX ./afs/kinetics400

une
la source