web-dev-qa-db-ja.com

シェルスクリプトは、nanoで保存すると機能しますが、Notepad ++で保存すると機能しません。

私がbashスクリプトをNotepad ++からSSH内のnanoエディターで新しいファイルにコピーして保存するとき。正常に動作します。 (sh ./install)。

しかし、ファイルを保存した場合(まったく同じ内容)、Webサーバーにアップロードし、同じマシンでWgetを使用してダウンロードします。構文エラーが発生します。エンコーディングを確認しましたが、同じようです。それ以来、問題が解決するかどうかを確認するために、大量の文字エンコードを使用してきました。また、wgetを使用してファイルをダウンロードしたら、ファイルを実行可能に設定しています。

ファイルは正常に実行され、nanoを使用してコピーして貼り付けるときにエラーは発生しません。これが何であるかについて何か考えはありますか?

4
user3185938

問題は行末に関連していると私は確信しています。あなたはおそらく、ラインのどこかで非* nixマシンを通過しているでしょう。また、Apache(Linuxで実行)がアップロードされたテキストファイルにWindowsスタイルの行末を追加していたときに問題が発生したため、同様の問題が発生する可能性があります。

テストするには、ダウンロードしたファイルを取得してodに渡します。長いファイルの場合は、最初の数行を取得してください。

head script.sh | od -c

出力を調べて、次のようなものがあるかどうかを確認します。

f   o   o  \r  \n

\rはキャリッジリターンであり、Windowsでは、行は* nixの\r\nではなく、\nで終了します。これが実際に問題であることが判明した場合は、キャリッジリターンを削除してファイルを修正できます。

sed -i 's/\r//g' script.sh
8
terdon

サーバー上に両方の形式のスクリプトがあるため、@ graemeが鋭く指摘しているように、単純なdiffを実行して、作業バージョンと問題のあるバージョンの違いを判別できます。

$ diff working.sh broken.sh

次のように並べて差分を行うこともできます。

$ diff -y working.sh broken.sh

なんらかのタイプミスが原因でスクリプトが機能しない場合は、-xスイッチをbashに追加することで、これらを検出できることがよくあります。これにより、スクリプトが冗長になります。

$ bash -x broken.sh

次のように、スクリプトの上部にあるShebang(#!/bin/bash)にこのスイッチを組み込むこともできます。

#!/bin/bash -x

行末

これは、ファイルをWindowsからUnix/Linuxシステムに移動するときによく発生します。この問題は、2つのプラットフォームで行の終わりがどのように示されるかに関係しています。詳細については、ウィキペディアの「 改行 」というタイトルで読むことができます。

サンプルファイルを作成します

$ echo -e "This is a file.\nThat I made on Unix.\n" > unixfile.txt

@terdonが彼の回答で説明しているように、sedを使用してこれらを取り除くことができます。また、dos2unixと呼ばれるツールを使用して同じことを行うこともできます。次の2つの方法のいずれかで使用できます。

$ dos2unix unixfile.txt

または、既存のファイルを上書きしたくない場合:

$ dos2unix -n oldfile.txt newfile.txt

上記のdiffを使用すると、次の2つのファイルを比較すると、次のような出力が得られます。

$ diff -y unixfile.txt winfile.txt 
This is a couple                            |   This is a couple
of lines of sample                          |   of lines of sample
text.                                       |   text.

違いがあるというだけで、違いを見分けることはできません。繰り返しますが、@ terdonの回答は、odを使用して問題をルーティングする1つの方法を示しています。もちろん、さまざまな方法を使用して、何が起きているのかを把握できます。

Vimを使用する

fileコマンドを使用

$ file unixfile.txt
winfile.txt: ASCII text 

$ file winfile.txt 
unixfile.txt: ASCII text, with CRLF line terminators

上記は、WindowsのファイルにCRLF(別名:キャリッジリターン+行末の改行文字)が含まれているという問題を浮き彫りにしています。これらの文字は16進数で0x0Dと0x0Aです。詳細については、 改行に関するウィキペディアの記事 を参照してください。

vimを使用して、問題を確認することもできます。

$ vim winfile.txt

これは、問題を確認するためにvimで何をするかを示す小さなシーケンスです。 CRLF文字は通常、Unixでは^Mとして表示されます。 Ctrl+M

ss of vim

シーケンスは、ファイルwinfile.txtをフォーマットされたUnixファイル(:e ++ff=unix)として再度開くことを示しています。これは、ファイルがWindows用にフォーマットされていることを自動検出しないようにvimに指示するため、^M行終了文字が表示されます。

5
slm