Windowsでバッチファイルを実行中にXPランダムに発生するエラーメッセージが見つかりました。
システムはname_of_labelで指定されたバッチラベルを見つけることができません
もちろんラベルは存在しました。このエラーの原因は何ですか?
実際、これを行うには2つの条件が必要です。
見る。 システムは指定されたバッチラベルを見つけることができません (および Batch-as-batch-can!
David A. Gray 言及 コメント内 (Windows 10で)何を見る Marshal の answer 2014年に表示(おそらくWindows 7または8上):スクリプト/バッチプログラム(.bat
または.cmd
) CALL
なしで実行すると、eol変換がトリガーされます。
過去35年間に何百ものバッチスクリプトを書いてきましたが、ラベルが見つからないという問題が発生したのは、ファイルの改行がWindows(CR/LF)から変換されて、 Unix(LF)、そうではありません。
以前にも同じ問題がありました。ただし、根本的な原因はまったくCRLFではありませんでした。これは、スクリプトでAntなどの外部プログラムを実行したが、Antの前にCALL
を付けなかったためです。そのため、バッチスクリプトで使用されるすべての外部プログラムをCALL
確認してください。
ここに問題とその修正方法があります。問題は、DOSバッチcmdプログラムのバグまたは機能です。まず、明確な問題の説明。 ":dothis"のようなターゲットラベルを持つDOSバッチファイルがあり、ラベルの最後にスペースがない場合、行末がUNIX行末である場合、バッチファイルは機能しません。これは、ファイルを使用する前にunix2dosを実行する必要があることを意味します。
根本原因は、DOSコマンドラインプロセッサ(シェルプログラム)であり、UNIXの行末文字をラベルの一部として使用します。 go to partはこれをラベルとして使用しないため、そのようなラベルは実際には存在しないため、検出されません。解決策は、各ターゲットラベルの最後に余分なスペースを置くことです。 UNIXの行末は、スペースがセパレータとして機能し、すべて機能するため、再生されなくなりました。
バッチファイルにUNIXの行末(行区切り記号)がある場合、これが発生することがあります。
nix2dos それだけで問題は解決するはずです。
また、他のスクリプトを呼び出すときに、呼び出し元の環境で呼び出すのではなく、CALLを使用することを確認する必要があります。
.cmdファイルとWindows 8で同様の問題が発生しました。解決策は、すべての行末をCR + LF DOSスタイルに変更することでした。バッチファイルがほとんど機能し、行を再配置すると効果が変わるため、問題は混乱を招きました。
.cmdファイルは次のようになりました。
call:function_A "..\..\folderA\"
call:function_B "..\..\folderB\"
call:function_C "..\..\folderC\"
call:function_D "..\..\folderD\"
goto:eof
:function_A
rem do stuff
goto:eof
...etc...
関数Cは、「指定されたバッチラベルが見つかりません」というエラーを引き起こします。奇妙なことに、呼び出しを再配置することで、それは消える可能性があります。行末を0x0Aから0x0D0Aに変更すると、修正されたようです。
おそらく、VonCは「バッチファイルはCRLF行末を使用する必要がある」ことを意味していました。
wordから開始コマンドをコピーしてコマンドウィンドウに貼り付けた後、この問題が発生しました。前面に "-"が付いたオプションがあり、DOSの "-"と同じように見えますが、そうではありませんでした:)問題を見つけるために....
少し異なるユースケース...
Windows Server 2012 Serverのpackerビルド中に、Shellプロビジョニングツールを使用して、batスクリプトを呼び出していました( OpenSSH)。現在、スクリプトはプロビジョニングされた仮想マシンのcmdで正常に機能していました(packerビルドにブレークポイントを置いて停止し、これを確認しました)...しかし、これらの呼び出しラベルが見つからないという問題で失敗していました。
行末はCRLF(Notepadd ++で確認済み)で問題ありませんでした。スクリプトはコマンドラインでも正常に機能していました。さらに、正常に実行するために使用することもあれば、失敗することもありますが、あるラベルで一度失敗すると、失敗は一貫していました。
最初は、呼び出し自体を展開し、サブルーチンコードをインライン化することで、サブルーチンを完全に削除し始めました。これは、呼び出しが1つしかなかったすべてのインスタンス(コードの重複なし)で行いました。
しかし、ええ、私は3,4か所から呼ばれた1つの潜水艦につまずきました。すべてを試した後、これは私のために働いたものです
8-10 REMステートメントをサブルーチンのすぐ上に追加します。はい、冗談ではありません!!
PS:このスクリプトは非常に古いものですが、管理者はその作業をpackerで行う必要がありました(これをAnsible/Chefに置き換える2日目の計画があります)。