Sind shell-Skripts, die empfindlich auf die Kodierung und zeilenendungen?
Ich mache eine NW.js app auf dem Mac, und möchten, führen Sie die app im dev-Modus durch Doppelklick auf ein Symbol. Ersten Schritt, den ich versuche zu machen meiner shell-Skript arbeiten.
Mit VSCode auf Windows (ich wollte um Zeit zu gewinnen), habe ich eine run-nw
Datei auf den root von meinem Projekt mit diesem:
#!/bin/bash
cd "src"
npm install
cd ..
./tools/nwjs-sdk-v0.17.3-osx-x64/nwjs.app/Contents/MacOS/nwjs "src" &
aber ich bekomme diese Ausgabe:
$ sh ./run-nw
: command not found
: No such file or directory
: command not found
: No such file or directory
Usage: npm <command>
where <command> is one of: (snip commands list)
(snip npm help)
npm@3.10.3 /usr/local/lib/node_modules/npm
: command not found
: No such file or directory
: command not found
Ich wirklich nicht verstehen kann:
- es scheint, dass es dauert, leere Zeilen als Kommandos. In meinem editor (VSCode) habe ich versucht zu ersetzen
\r\n
mit\n
(im Fall der\r
Probleme schafft), aber es ändert sich nichts. - es scheint, dass es nicht die Ordner (mit oder ohne
dirname
Anleitung), oder es vielleicht nicht wissen, über diecd
Befehl ? - es scheint, dass Sie es nicht verstehen, die
install
argumentnpm
- der Teil, der wirklich weirds mich, ist, dass es immer noch läuft die app (wenn ich einen
npm install
manuell)...
Nicht in der Lage, damit es richtig funktioniert, und zu Ahnen, etwas unheimliches mit der Datei selbst, habe ich mir eine neue ein direkt auf dem Mac, indem Sie vim diese Zeit. Ich habe die gleichen Daten eingegeben Anweisungen, und... jetzt funktioniert es ohne Problem.
Ein diff auf die beiden Dateien, die zeigt genau null Unterschied.
Was kann der Unterschied sein? Was das erste Skript nicht funktioniert? Wie finde ich das heraus?
Update
Folgenden die akzeptierte Antwort, Empfehlungen, nach der falschen Zeilenenden zurück kam, überprüfte ich mehrere Dinge. Es stellt sich heraus, dass, seit ich schrieb meine ~/.gitconfig
von meinem Windows-Rechner hatte ich autocrlf=true
, so dass jedes mal, wenn ich veränderte die bash-Datei unter Windows, es re-legen Sie die Zeilenenden zu \r\n
.
So, zusätzlich zu Laufenden dos2unix (die Sie haben zu installieren mit Homebrew auf dem mac), wenn Sie mit Git, überprüfen Sie Ihre config.
dos2unix
?Wenn Sie ein shell-Skript unter Linux, zumindest alle shell-Implementierungen, die ich bisher begegnet sind, würde sich aufregen, wenn Sie einen \r irgendwo. Nein, Sie sagen, dass Sie entfernt haben, \r, und ich hoffe, dass Sie verifiziert, dass Sie wirklich Weg sind. Für der sicheren Seite zu sein, sollten Sie Ihre Datei im hexadezimal-Ebene, um sicherzustellen, dass Sie nicht haben, andere komische Zeichen. Der nächste Schritt wäre dann das script ausführen mit
sh -x ./run-nw
, um weitere Informationen zu erhalten.Ein anderer guter Befehl um zu schauen für komische Zeichen in einer text-Datei ist
LC_ALL=C cat -vet /path/to/file
. Wenn die Datei normal, es wird normal Aussehen (außer für die mit einem "$" am Ende jeder Zeile). Alles abnormale sollte, stehen ziemlich gut. DOS/Windows-Dateien haben "^M$" am Ende der Zeilen.InformationsquelleAutor thomasb | 2016-09-16
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja. Bash-Skripte sind empfindlich für line-Endungen, die beide in das Skript selbst und in Daten verarbeitet werden. Sie sollten Unix-style line endings, D. H., jede Zeile wird beendet mit einem Zeilenvorschub-Zeichen (dezimal 10, hex 0A in ASCII).
DOS/Windows-Zeilenenden im Skript
Mit Windows-oder DOS-Stil Zeilenenden , jede Zeile wird beendet mit einem Wagenrücklauf gefolgt von einem Zeilenvorschub-Zeichen. Wenn eine Skript-Datei mit Windows-Zeilenenden, Bash sieht die Datei als
Hinweis: ich habe die caret-notation zum darstellen von nicht-Druck-Zeichen, d.h.,
^M
wird verwendet, um zu vertreten das Carriage-Return-Zeichen (dargestellt als\r
in anderen Kontexten); dies ist die gleiche Technik, die voncat -v
und Vim.In diesem Fall, der Wagenrücklauf (
^M
oder\r
) wird nicht behandelt, wie Leerzeichen. Bash interpretiert die erste Zeile nach der shebang (die aus einem einzelnen carriage-return-Zeichen) als Namen für einen Befehl/Programm laufen zu lassen.^M
gibt: command not found
"src"^M
(odersrc^M
), druckt es: No such file or directory
install^M
stattinstall
als argument zunpm
die Ursachennpm
zu beschweren.DOS/Windows-Zeilenenden im input-Daten
Wie oben, haben Sie eine input-Datei mit Wagenrücklaufzeichen:
dann wird es Aussehen, ganz normal in der Redaktion und beim schreiben auf dem Bildschirm, sondern Werkzeuge produzieren kann seltsame Ergebnisse. Zum Beispiel
grep
nicht finden, die Linien sind offensichtlich:Angehängten text wird stattdessen die Zeile überschreiben, weil der Schlitten zurück bewegt den cursor an den Anfang der Zeile:
String-Vergleich scheinen zu scheitern, obwohl die Saiten gleich erscheinen beim schreiben auf dem Bildschirm:
Lösungen
Die Lösung ist die Datei zu konvertieren zu verwenden, Unix-style line endings. Es gibt eine Reihe von Möglichkeiten, wie dies erreicht werden kann:
Diese kann getan werden, mithilfe der
dos2unix
Programm:Öffnen Sie die Datei in einem fähig Texteditor (Sublime, Notepad++, Notepad) und konfigurieren Sie das speichern von Dateien mit Unix-Zeilenenden, z.B. mit Vim, führen Sie den folgenden Befehl, bevor Sie (wieder)zu speichern:
Wenn Sie eine version der
sed
Dienstprogramm, das unterstützt die-i
oder--in-place
option, z.B., GNUsed
Sie können den folgenden Befehl ausführen, um strip trailing carriage returns:Mit anderen Versionen von
sed
haben, könnten Sie die Ausgabe-Umleitung zum schreiben in eine neue Datei. Verwenden Sie einen anderen Dateinamen für die Umleitung Ziel (es kann sein, später umbenannt).Ähnlich, die
tr
übersetzung-filter kann verwendet werden, um zu löschen Sie unerwünschte Zeichen aus der Eingabe:Cygwin-bash -
Mit der Bash-port für Cygwin gibt es eine benutzerdefinierte
igncr
option, die eingestellt werden können, ignoriert den Zeilenumbruch in Zeile enden (vermutlich, weil viele Benutzer die systemeigene Windows-Programme zum Bearbeiten der text-Dateien). Diese Einstellung gilt für die aktuellen - shell-Prozess, so kann es nützlich sein, wenn sourcing Dateien mit überflüssigen Absatzmarken.Nützliche Dienstprogramme
Den
file
- Dienstprogramm ist nützlich, um schnell zu sehen, welche Zeilenenden verwendet werden, in einer text-Datei. Hier ist, was er druckt für jede Datei-Typ:Bourne-Again shell script, ASCII text executable
Bourne-Again shell script, ASCII text executable, with CR line terminators
Bourne-Again shell script, ASCII text executable, with CRLF line terminators
Die GNU-version des
cat
- Dienstprogramm hat eine-v, --show-nonprinting
option, die zeigt nicht-druckbare Zeichen.Den
dos2unix
Dienstprogramm ist speziell geschrieben für das konvertieren von Textdateien zwischen Unix -, Mac-und DOS-Zeilenenden.Nützliche links
Wikipedia hat eine exzellente Artikel abdecken, die viele verschiedene Arten von markieren das Ende einer Zeile der text, die Geschichte von solchen Codierungen und wie Zeilenumbrüche behandelt werden, in verschiedenen Betriebssystemen, Programmiersprachen und Internet-Protokolle (z.B. FTP).
Dateien mit dem klassischen Mac OS Zeilenenden
Mit Classic Mac OS (pre-OS X), jede Zeile wurde beendet mit einem Carriage Return (dezimal 13, hex 0D in ASCII). Wenn eine Skript-Datei gespeichert wurde, mit solchen Zeilenenden, Bash würde nur eine lange Zeile etwa so:
Seit dieser langen Zeile beginnt mit einer Raute (
#
), Bash behandelt die Linie (und die ganze Datei als ein einziges Kommentar.Hinweis: In 2001, Apple Mac OS X basiert auf BSD-abgeleiteten NeXTSTEP Betriebssystem. Als Ergebnis, OS X verwendet Unix-Stil LF-nur die Zeilenenden und da dann text-Dateien beendet mit einem CR sind sehr selten geworden. Trotzdem denke ich, es lohnt sich, um zu zeigen, wie Bash versuchen würde zu interpretieren solcher Dateien.
Tolle Erklärung, nur ein kleines Stück, das hier fehlt: gibt es tatsächlich einen Grund dafür, dass diese Tage für die echten bash weiter zu behandeln
\r
als ein sinnvolles Zeichen am Ende der Zeile?InformationsquelleAutor Anthony Geoghegan
Einen weiteren Weg, um loszuwerden, die unerwünschte CR ('\r') - Zeichen ist, laufen die
tr
Befehl, zum Beispiel:tr -d '\r' < myFile > myFile
das ist KEINE gute Idee, als IhremyFile
wird jetzt gelöscht werden oder zumindest gekürzt. Bei der Verwendung von< infile > outFile
Umleitungen, verwenden Sie immer unterschiedliche Dateinamen fürinfile
undoutfile
. Sie können dann benennen Sie wie erforderlich. Viel Glück an alle.Auch
tr
ungewöhnlich ist, dass es sich weigert, eine Datei name-argument; Sie verwenden Sie die Umleitung wietr x y <inputfile
(nichttr x y inputfile
)InformationsquelleAutor Igor Soudakevitch
Auf JetBrains Produkte (PyCharm, PHPStorm, IDEE, usw.), Sie müssen klicken Sie auf auf
CRLF
/LF
zu Umschalten zwischen den zwei Arten von line-Separatoren (\r\n
und\n
).InformationsquelleAutor Pedro Lobito
Der einfachste Weg, die auf der MAC - /Linux - erstellen Sie eine Datei mit "touch" - Befehl, öffnen Sie diese Datei mit VI oder VIM-editor, fügen Sie den code ein und speichern Sie. Dies würde automatisch zu entfernen das windows-Zeichen.
Leicht zu merken und funktioniert.
Stimmt, aber kopieren/einfügen im vi/vim ist nicht das, was ich nennen würde "einfachste" 😀 ich werde un-downvote, wenn.
Einverstanden, eine Art life-hack für Leute wie mich, die keine Experten in shell-scripting 🙂
touch
ist ein ProgrammInformationsquelleAutor danR
Kommen aus einem doppelten, wenn das problem ist, dass Sie Dateien, deren Namen enthalten
^M
am Ende, Sie können Sie umbenennen mitRichtig wollen, um zu beheben, was verursacht diese Dateien, um gebrochen haben Namen an Erster Stelle (wahrscheinlich ein Skript, welches erstellt werden sollte, Sie
dos2unix
ed und führen Sie dann erneut?) aber manchmal ist dies nicht machbar.InformationsquelleAutor tripleee