Pourquoi est-ce que j'obtiens "ligne 1: $ ': \ r': commande introuvable"?

13

J'ai utilisé Cygwin sur mon ordinateur portable (DOS). J'ai une collection de scripts de mes collègues et la mienne. Je ne suis pas un informaticien, je ne connais pas Unix. Je suis la syntaxe de mes collègues et capable de gérer quelques choses simples.

Les scripts fonctionnaient bien sur mon ancien ordinateur portable. Je viens de changer d'ordinateur portable, d'installer Cygwin. Lorsque j'exécute mes scripts, ils ne fonctionnent pas. Voici un exemple du message d'erreur que j'obtiens:

line 1: $':\r': command not found
line 5: syntax error near unexpected token `$'\r''
line 5: `fi

Voici les 5 premières lignes de mon script

:
iter=1
if [ -f iter.txt ]
   then rm ./iter.txt 
fi  

Quelqu'un peut-il expliquer comment je peux contourner ce problème?

TPham
la source

Réponses:

29

Vous avez des fins de ligne de style Windows.

La commande no-op :est lue à la place comme :<carriage return>, affichée comme :\rou plus complètement comme $':\r'.

Courez dos2unix scriptnameet ça devrait aller.


Si vous n'en avez pas dos2unix, ce qui suit devrait fonctionner presque n'importe où (et j'ai testé sur MobaXterm sous Windows):

vi -b filename

Ensuite vi, saisissez:

:%s/\r$//
:x

Vous êtes prêt à partir.


Dans vim, pour lequel vous utilisez Cygwin vi, il existe plusieurs façons de procéder. Un autre implique le fileformatréglage, qui peut prendre les valeurs dosou unix. Soit le modifier explicitement après avoir chargé le fichier avec

set fileformat = unix
ou forcer explicitement le format de fichier lors de l'écriture du fichier avec

: w + fileformat = unix

Pour en savoir plus à ce sujet, consultez les nombreuses questions et réponses couvrant ce sujet, notamment:

Caractère générique
la source
Je veux juste clarifier, "iter = 1" est mon compteur qui sera utilisé pour le nombre de tours d'un algorithme mathématique que mon modèle devra répéter plus tard au-delà de la ligne 5. Je viens de publier les 5 premières lignes pour aller avec le Message d'erreur. Tous les commentaires et instructions sont grandement appréciés !!
TPham
Je viens d'essayer la commande suggérée "$ tr -d ....." mais il y a un problème avec mon ordinateur portable. Il ne revient pas à "$" mais le ">" apparaît à l'écran à la place. Je dois utiliser le contrl C pour sortir. Ensuite, j'ai testé le script pour voir si le problème est résolu, mais il est toujours là. Désolé, mes connaissances dans ce domaine sont très minimes! J'essaie d'utiliser ma collection de scripts car ils aident beaucoup mon travail. Merci à tous pour votre patience et votre aide.
TPham
@TPham, voir modifier. Si cela fonctionne, assurez-vous d'utiliser la coche à côté de la réponse pour "l'accepter". (Acceptez la réponse qui a le mieux résolu votre problème.) Unix.stackexchange.com/help/someone-answers
Wildcard
1
Les commandes qui sont des mots ne sont pas vraiment plus compliquées pour un novice qu'une mystérieuse incantation qui est presque entièrement ponctuée. Cela n'a pas besoin d'une réponse distincte. Il a simplement besoin de cette réponse pour mentionner qu'il vimpeut le faire de deux manières, dont l'une utilise des mots. Ou, mieux encore, pour indiquer où cette tâche subordonnée a été répondue encore et encore ici de manière beaucoup plus détaillée que toute réponse sur cette page, y compris unix.stackexchange.com/questions/88811 juste pour les débutants.
JdeBP
1
Notez que vi -b, \rsont des extensions vim de toute façon. pas POSIX, pas dans nvi, elvis, Solaris vi ...
Stéphane Chazelas
10

Cela est dû au fait que le script a été enregistré par un éditeur qui utilise des fins de ligne DOS (comme Notepad ++, par exemple). Vous devrez les supprimer de vos scripts.

Pour ce faire, utilisez soit dos2unixsur le fichier de script, soit

$ tr -d '\r' <script >script.new && mv script.new script

(cela supprimera tous les retours chariot de n'importe où dans le script)


Quant au code du script:

:
iter=1
if [ -f iter.txt ]
   then rm ./iter.txt 
fi  

Cela devrait ressembler à quelque chose

iter=1
if [ -f "./$iter.txt" ]; then
   rm "./$iter.txt"
fi

Cela supprime le fichier 1.txtdu répertoire actuel, s'il existe. La :commande ne fait rien (presque) et peut être supprimée. La itervaleur de la variable doit être utilisée comme $iter, et être citée. Et puis je suis peut-être plus explicite que nécessaire en ./disant que le fichier doit être trouvé dans le répertoire courant.

Si vous avez l' intention de transformer cela en une boucle (ici, supprimant tous les fichiers 1.txt, 2.txt..., 10.txt):

iter=1
while [ "$iter" -le 10 ]; then
    if [ -f "./$iter.txt" ]; then
        rm "./$iter.txt"
    fi
    iter=$(( iter + 1 ))
done

Ou, si nous nous sentons sournois / paresseux,

rm -f {1..10}.txt

dans les coquilles qui comprend l'expansion de l'accolade.

Kusalananda
la source
3
Notepad ++ a en fait la possibilité d'utiliser des sauts de ligne Windows / Mac / Linux. Vous avez juste besoin d'aller dans le menu Édition puis de Conversion EOL-> Unix (LF). Ou vous pouvez simplement double-cliquer dans le coin inférieur droit où il est dit Windows (CR LF)et le changer enUnix (LF)
jesse_b
Merci à tous pour vos instructions. Je voudrais clarifier: le "iter = 1" est un compteur que j'utilise plus tard pour mon objectif principal, au-delà de la ligne 5.
TPham
@TPham Vous êtes les bienvenus. Je m'ennuyais juste et j'ai pris votre code et je me suis laissé impressionner par lui.
Kusalananda
Ou rm -f [1-9].txt 10.txt. Mais ce n'est pas totalement équivalent logiquement, comme s'il n'y avait pas de fichiers 1-9 mais qu'il y a un fichier appelé littéralement, [1-9].txtil sera supprimé. : D
Wildcard
5

Vos scripts ont des terminaisons de ligne incorrectes. Windows utilise CR + LF (\ r \ n), Unix utilise LF (\ n) et Classic MacOS utilise CR (\ r). Vous devrez modifier les fins de ligne sur tous les fichiers concernés, à l'aide d'un éditeur de texte ou d'un outil autonome comme dos2unix.

Les systèmes FTP et de contrôle de version tels que SVN ont tendance à être capables de convertir les fins de ligne de manière appropriée, donc vous voudrez peut-être examiner ces options pour le transfert de fichiers à l'avenir.

Si ces fichiers ne sont pas transférés, mais simplement utilisés sur une seule machine, vous voudrez trouver les paramètres des fins de ligne dans votre éditeur de texte préféré. La plupart de ceux qui sont annoncés comme "pour les programmeurs" auront une telle option.

Renard
la source
Merci à tous pour vos instructions utiles. Je viens d'essayer dos2unix mais il semble que je ne l'ai pas. Recherche et réessaye.
TPham
3

En guise de réponse supplémentaire, permettez-moi d'ajouter quelques notes / conseils ...

Tout d'abord, pour les fichiers texte normaux, vous pouvez facilement déterminer s'ils ont une ligne Unix ou DOS se terminant à l'aide de la filecommande. Par exemple:

$ file test.txt
test.txt: ASCII text, with CRLF line terminators
$ dos2unix test.txt
dos2unix: converting file test.txt to Unix format...
$ file test.txt
test.txt: ASCII text

Notez mon utilisation de dos2unix. Je vous recommande fortement de l'installer. Selon la façon dont vous utilisez Cygwin, vous pouvez constater que vous devez effectuer cette conversion suffisamment souvent pour que la commodité soit la bienvenue. Plus important encore, il n'y a aucun risque d'erreur comme vous obtenez avec les modifications manuelles décrites ici.

Pour installer, démarrez l'exécutable Cygwin principal. C'est celui avec le nom comme setup-x86_64.exe ou quelque chose dans ce sens. Assurez-vous de voir un écran comme celui-ci:

entrez la description de l'image ici

Comme vous avez déjà effectué l'installation principale, vous devriez pouvoir cliquer sur Suivant jusqu'à ce que vous obteniez l'écran de sélection. Sélectionnez Complet dans la liste déroulante et entrez "dos2" dans la zone de recherche et choisissez l'outil comme indiqué ici:

entrez la description de l'image ici

Cliquez à nouveau sur Suivant et laissez l'installation se terminer. C'est ça. S'amuser. Cygwin, à l'exception de cet inconvénient occasionnel, est un package génial.

Couche B
la source
Merci beaucoup pour votre instruction Couche B! Ce groupe Stack Exchange est très utile. J'apprécie vraiment ce soutien.
TPham
1

Sinon dos2unix, il y a aussi 'flip'

$ flip -u votrefichier.txt

le retournera en utilisant les fins de ligne unix.

chai
la source
1

J'utilise Notepad ++ pour modifier mes scripts bash (.sh) en me connectant au serveur par WinSCP
(pour configurer l'éditeur WinSCP sur Notepad ++: https://winscp.net/eng/docs/ui_editor_preferences )

C'est très pratique pour ouvrir des fichiers depuis des serveurs pour les éditer / enregistrer au lieu de l' éditeur " Vim ".
Lorsque vous ouvrez le fichier dans Notepad ++ , double-cliquez sur la 7e colonne dans la barre d'état en bas et sélectionnez " Unix (LF) ".

entrez la description de l'image ici

De plus, vous devez changer le 8ème en encodant -> Encoder en UTF-8 dans la barre supérieure.

Alper t. Turker
la source
0

Vous n'avez pas besoin de modifier l'encodage de ligne du fichier réel pour que Cygwin's Bash fonctionne avec bonheur avec les encodages de fin de ligne Mac et Windows. Il y a une option que vous devez simplement activer.

Mettez simplement à jour votre ~/.bash_profilecontenu

export SHELLOPTS
set -o igncr

Voir https://ptolemy.berkeley.edu/projects/chess/softdevel/faq/5.html

swdev
la source