行番号とインデントをつけるために、コピペしました。
BAT
1@echo off
2set /p data=今日の日付を入れて下さい (例:2025/11/20):
3
4call set data=%data%
5
6if /i "%data%"=="2025/11/20" (
7 echo 今日は2025/11/20です。
8 set /p nanana=続行しますか? (y/n):
9 set nanana=%nanana%
10 if /i "%nanana%"=="Y" (
11 echo Yが入力されました。
12 ) else (
13 echo Nが入力されました。
14 )
15) else (
16 echo 日付が合致しません。
17)
18pause
6行目の(に対応する)ですが、おそらく15行目行頭の)のつもりなのでしょう。
しかし実際は、7行目以降に最初に出てきた)で、6行目の(は閉じてしまいます。()を二重引用符"で囲むなど引用(クォート)されている場合は除外)
それは、8行目の(y/n)の)です。で、そのあとの:が括弧の外なのでエラー。
( echo ABC ): の1行を実行してみると、同じく「: の使い方が誤っています。」というエラーになるかと思います。
対応としては、
案1:構文的な意味を持つ()を使わずに[y/n]などとする。
案2:クォート記号^を使って、(y/n^)として、)を「構文的な意味を持たない単なる文字列」とする。
他の言語でも、print("二重引用符というのは"という文字のことです")と書くと、2つ目の"が「閉じ引用符」とみなされてその次が構文エラーになりますが、そういうのと同じです。
案1:print('二重引用符というのは"という文字のことです')
案2:print("二重引用符というのは\"という文字のことです")
ただ、これを解決しても、駄目ですね。以下、上記の修正をした前提で続けると、
6行目から17行目までが、長いIF文で、この構文解析は6-17行目丸ごと一括で行われます。
10行目の%nanana%の変数展開(変数名から変数の値への置き換え)は、この構文解析時(構文解析直前)に行われますが、その時点では変数nananaはおそらく「空」なので、10行目は変数展開の結果if /i ""=="Y" (となり、そのあとで実行されるので、IF条件は常に偽です。
この間違いは、1行目の@echo offを削除して実行される文を画面表示すると、(注意深ければ)気づけます。
"%nanana%"の変数展開を正しくするには、
案1:括弧の中で代入した変数はそのあとの括弧内では参照しない
⇒ 処理を括弧の外に出してcallで呼ぶ
案2:「遅延環境変数」を使う
⇒ setlocal enabledelayedexpansionを冒頭に入れて、"!nanana!"と!で参照する。ただし、他のバッチ処理と組み合わせて使うときはsetlocalの意味の理解が必要。
案2は、BATスクリプト内に単なる文字列の!の文字がなくて、変数の値にも!が含まれ得ないときは、単純修正で済みます。!が使われている場合はよく考える必要あり。
案1は修正が多いですが、括弧の中身が複雑な時は、括弧を使わず中身を全部サブルーチンにしてCALLで呼ぶほうがデバッグが楽になります。
あと、4行目と9行目は無意味なので削除しましょう。うまくいかず、試行錯誤途中で追加したのですかね?
このようにY/Nを聞くだけなら、choiceを使うという案3もあります。
BAT
1 choice /M 続行しますか
2 if errorlevel 2 (
3 echo Nが入力されました。
4 ) else (
5 echo Yが入力されました。
6 )
使い方は、choice /?に書いてあります。Yだとerrorlevelは1で、Nだとerrorlevelは2。
if %errorlevel% == 1は前述の理由で括弧内に書くと意図しない結果になるので、%での変数展開をしないためにif errorlevel 値の構文を使います。
if errorlevel 1は「errorlevelが1ならば」ではなくて「errorlevelが1以上ならば」なので、2を先にチェックしないといけない。
参考
バッチスクリプトのデバッグをするときは、
・@echo offは書かない
・ExplorerからBATファイルダブルクリックで実行するのではなくて、コマンドプロンプトかPowerShell画面から、カレントディレクトリをBATファイルのある場所に移動してから、BATファイル名入力して実行する
(ダブルクリックでの実行時に画面が自動で閉じるのを防ごうとpauseを入れても、構文エラーだとpauseコマンドの記述が認識されて実行される前にエラーになり、構文エラーのメッセージは一瞬ですぐ消える)