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?
Vous avez des fins de ligne de style Windows.
La commande no-op :
est lu à la place comme :<carriage return>
, affiché comme :\r
ou plus complètement comme $':\r'
.
Courir dos2unix scriptname
et ça devrait aller.
Si vous n'avez pas dos2unix
, ce qui suit devrait fonctionner presque n'importe où (et j'ai testé sur MobaXterm sous Windows):
vi -b filename
Puis dans vi
, tapez:
:%s/\r$//
:x
Vous êtes prêt à partir.
Dans vim
, qui est ce que vous utilisez sur Cygwin pour vi
, il existe plusieurs façons de procéder. Un autre implique le paramètre fileformat
, qui peut prendre les valeurs dos
ou unix
. Soit le modifier explicitement après avoir chargé le fichier avec
set fileformat = unix
: w + fileformat = unix
Pour plus d'informations à ce sujet, consultez les nombreuses questions et réponses couvrant ce sujet, notamment:
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 dos2unix
Sur 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.txt
Du répertoire actuel, s'il existe. La commande :
Ne fait rien (presque) et peut être supprimée. La valeur de la variable iter
doit être utilisée comme $iter
, Et être citée. Et puis je suis peut-être plus explicite que nécessaire en utilisant ./
Pour dire que le fichier doit être trouvé dans le répertoire courant.
Si vous prévoyez de transformer cela en boucle (ici, en 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.
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, soit avec un éditeur de texte, soit avec 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 en cours de transfert, mais simplement utilisés sur une seule machine, alors 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.
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 commande file
. 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:
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:
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.
Sinon dos2unix, il y a aussi 'flip'
$ flip -u votrefichier.txt
le retournera en utilisant les fins de ligne unix.
J'utilise Notepad ++ pour éditer 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) ".
De plus, vous devez changer le 8ème en encodant -> Encoder en UTF-8 dans la barre supérieure.
Vous n'avez pas besoin de modifier l'encodage de ligne du fichier réel pour que Bash de Cygwin 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_profile
donc il contient
export SHELLOPTS
set -o igncr
Voir https://ptolemy.berkeley.edu/projects/chess/softdevel/faq/5.html