“.bat”파일에서 명령 줄 매개 변수를 확인하는 방법은 무엇입니까?


103

내 OS는 Windows Vista입니다. 사용자가 명령 줄 매개 변수를 입력하는지 여부를 확인해야하는 ".bat"파일이 필요합니다. 그렇다면 매개 변수가 다음과 같으면 -b다른 작업을 수행합니다. "잘못된 입력"플래그를 지정합니다. 사용자가 명령 줄 매개 변수를 입력하지 않으면 내가 뭔가를 할 것입니다. 다음 .bat 파일을 만들었습니다. 케이스 -b와 동일하지 않지만 작동 -b하지만 사용자가 명령 줄 매개 변수를 전달하지 않으면 실패합니다.

항상 오류가 발생합니다.

GOTO was unexpected at this time.

아무도 내가 여기서 뭘 잘못하고 있는지 말해 줄 수 있습니까?


ECHO OFF
CLS
ECHO.

IF [%1]==[/?] GOTO BLANK

IF %1=="-b" GOTO SPECIFIC

IF NOT %1=="-b" GOTO UNKNOWN

:SPECIFIC

ECHO SPECIFIC

GOTO DONE

:BLANK

ECHO No Parameter

GOTO DONE

:UNKNOWN

ECHO Unknown Option

GOTO DONE

:DONE

ECHO Done!

GOTO BLANK다른 두 IF문장 에 대괄호 ( 줄 에있는 것과 같은)를 추가 하면 문제가 해결됩니까?
Jeremiah Willcock

답변:


141

매개 변수가 비어 있는지 확인해야합니다. if "%~1"=="" goto blank

이 작업을 마치면 -b에서 if / else 스위치를 수행합니다. if "%~1"=="-b" (goto specific) else goto unknown

매개 변수를 따옴표로 묶으면 공백 / 빈 / 누락 된 매개 변수와 같은 항목을 더 쉽게 확인할 수 있습니다. "~"는 큰 따옴표가 명령 줄 인수에있는 경우 제거되도록합니다.


작동합니다 !! "else"만 허용되지 않습니다. 오류가 발생합니다. 'else'는 내부 또는 외부 명령, 작동 가능한 프로그램 또는 배치 파일로 인식되지 않습니다. 그래서 "-b와 같지 않음"사례에 대해 또 다른 IF를 추가했습니다. 빠른 답변에 감사드립니다.
javauser71

7
ELSE는 IF와 같은 줄에 있거나 대괄호 바로 뒤에 있어야합니다
jeb

4
% 1에 공백이 포함되어 있으면 작동하지 않는 것 같습니다. 실행 파일의 전체 경로 일 수 있습니다. 값에 공백이있는 매개 변수에서도 작동하는 솔루션에 대해서는 Jeremiah Willcock의 답변 을 참조하십시오 .
Mark A. Fitzgerald 2014

인수가 인 경우 허용되지 않습니다 File.이 경우에는 exist또는 만 확인해야합니다 not exist. 이것이 당신의 주장이 잘 정의되어야하는 이유이거나 단순히 powershell 또는 vbScript를 사용해야하는 이유입니다 (80 년대라면 ..)

1
이것은 run.bat "a b". "%1"==""arg에 공백이 있으면 충돌합니다. stackoverflow.com/a/46942471
wisbucky

27

답변 은 http://ss64.com/nt/if.html참조하십시오 . 명령이 IF [%1]==[] GOTO NO_ARGUMENT유사합니다.


1
이뿐 만 아니라 작동합니다! .NET과 달리 작동합니다 "%1"=="". 나는 내 자신의 대답에서 그것에 대해 자세히 설명해야합니다.
Tomasz Gandor 2016

1
예를 들어, % 1이 인용되면 중단됩니다 foo.bat "1st parameter" 2nd_param. stackoverflow.com/questions/2541767/…
matt wilkie

[%1]==[-b]arg가 인용되면 사용 은 일치하지 않습니다. 예 run.bat "-b". stackoverflow.com/a/46942471
wisbucky

20

짧은 대답-대괄호 사용 :

if [%1]==[] goto :blank

또는 (따옴표 붙은 인수를 처리해야하는 경우 아래 편집을 참조하십시오) :

if [%~1]==[] goto :blank

왜? 당신은 물어볼 수 있습니다. Jeremiah Willcock이 언급했듯이 http://ss64.com/nt/if.html- 그들은 그것을 사용합니다! 좋아요,하지만 따옴표에 무슨 문제가 있습니까?

다시 한 번, 짧은 대답은 "마 법적"입니다. 때로는 큰 따옴표 (큰 따옴표)가 작은 따옴표 (큰 따옴표)로 변환되기도합니다. 그리고 그들은 시작을 위해 일치해야합니다.

이 작은 스크립트를 고려하십시오.

@rem argq.bat
@echo off

:loop 
if "%1"=="" goto :done
echo %1
shift
goto :loop

:done
echo Done.

테스트 해 보겠습니다.

C:\> argq bla bla
bla
bla
Done.

작동하는 것 같습니다. 하지만 이제 두 번째 기어로 전환하겠습니다.

C:\> argq "bla bla"
bla""=="" was unexpected at this time.

Boom 이것은 참으로 평가되지 않았고 거짓으로 평가되지 않았습니다. 스크립트가 죽었습니다. 라인 어딘가에서 원자로를 끄려면 운이 좋을 것입니다. 이제 당신은 Harry Daghlian처럼 죽을 것입니다.

당신은 생각할 수 있습니다-좋습니다, 인수는 따옴표를 포함 할 수 없습니다. 그렇게하면 이런 일이 발생합니다. 틀렸다 여기에 몇 가지 위로가 있습니다.

C:\> argq ""bla bla""
""bla
bla""
Done.

오 예. 걱정하지 마십시오 - 때때로됩니다 작동합니다.

다른 스크립트를 시도해 보겠습니다.

@rem args.bat
@echo off

:loop 
if [%1]==[] goto :done
echo %1
shift
goto :loop

:done
echo Done.

위의 경우에 제대로 작동하는지 직접 테스트 할 수 있습니다. 이것은 논리적입니다. 따옴표는 대괄호와 관련이 없으므로 여기에는 마법이 없습니다. 그러나 대괄호로 인수를 spicing하는 것은 어떻습니까?

D:\>args ]bla bla[
]bla
bla[
Done.

D:\>args [bla bla]
[bla
bla]
Done.

거기에 행운이 없습니다. 대괄호는 cmd.exe의 파서를 질식시킬 수 없습니다 .

잠시 사악한 인용문으로 돌아가 보겠습니다. 논쟁이 따옴표로 끝났을 때 문제가 발생했습니다.

D:\>argq "bla1 bla2"
bla2""=="" was unexpected at this time.

통과하면 어떻게 되나요?

D:\>argq bla2"
The syntax of the command is incorrect.

스크립트가 전혀 실행되지 않습니다. 동일 args.bat:

D:\>args bla2"
The syntax of the command is incorrect.

그러나 다음 "과 같은 경우-문자 의 수가 "일치"(즉-짝수) 되면 무엇을 얻 습니까?

D:\>args bla2" "bla3
bla2" "bla3
Done.

NICE-.bat 파일이 명령 줄 인수를 분할 하는 방법에 대해 배웠기를 바랍니다 (힌트 : * bash에서와 정확히 같지 않음). 위의 인수에는 공백이 있습니다. 그러나 따옴표는 자동으로 제거되지 않습니다.

그리고 argq? 그것에 대해 어떻게 반응합니까? 예측 가능 :

D:\>argq bla2" "bla3
"bla3"=="" was unexpected at this time.

그래서-당신이 말하기 전에 생각하세요 : "뭔지 알아? 그냥 따옴표를 사용하세요. [왜냐하면,이게 더 멋져 보이거든요]".

편집하다

최근에이 답변에 대한 의견이있었습니다. 인용 된 인수를 전달하고 인용되지 않은 것처럼 처리하는 sqare 대괄호는 "처리 할 수 ​​없습니다".

구문 :

if "%~1"=="" (...)

큰 따옴표로 인해 새로 발견 된 미덕이 아니라 첫 번째와 마지막 문자가 큰 따옴표 인 경우 인수 변수에서 따옴표를 제거하는 깔끔한 기능의 표시입니다.

이 "기술"은 대괄호로도 잘 작동합니다.

if [%~1]==[] (...)

이것을 지적하는 것이 유용했기 때문에 새로운 답변에 찬성 투표를했습니다.

마지막으로, 큰 따옴표 팬, 형식의 인수가 ""책에 존재합니까, 아니면 비어 있습니까? 그냥 물어 ';)


1
[%1]==[-b]arg가와 같이 인용되면 대괄호 는 일치하지 않습니다 run.bat "-b". stackoverflow.com/a/46942471
wisbucky

역사적으로 참고 : [%1]==[-b]"%1"=="-b"승리 98 및 이전 버전 MS / PC-DOS 시스템 배치 스크립트에 대한 동일 하였다. win 2000 / NT는 if "%~1"=="-b"큰 따옴표가 특별한 의미를 갖는 구문을 도입 한 이후 로, 더 강력한 보호를 제공하므로 스크립트를 코딩해야하는 방식입니다. 큰 따옴표는 특수 문자의 의미를 이스케이프합니다 (명령 줄에서 시도 & | 및 % 문자). 99.9 %의 예제는 큰 따옴표 구문으로 작동합니다. 예제 argq bla2" "bla3는 대괄호를 정당화하는 경우 일뿐입니다. 삽입 된 큰 따옴표는 재난을위한 레시피입니다.-그냥 말하면됩니다.
Skip R

@SkipR-이것이 Windows의 파일 시스템에서 이름에 이러한 특수 문자를 사용할 수없는 이유입니다. 수학적 증거는 없지만 cmd쉘 에서 모든 것을 인용 할 수있는 것은 아니라고 생각합니다 . 다른 시스템에서는 NUL 문자를 포함하여 모든 것을 인용 할 수 있습니다. ( stackoverflow.com/questions/2730732/…)- 이 질문은 단지 외부 프로그램을 사용해야한다는 것을 보여줍니다.
Tomasz Gandor

8

내가 구독하는 다른 답변 외에도 명령 /I스위치 사용을 고려할 수 있습니다 IF.

... / I 스위치가 지정되면 대소 문자를 구분하지 않는 문자열 비교를 수행합니다.

매개 변수를 지정하기 위해 사용자에게 대소 문자를 구분하지 않는 유연성을 제공하려는 경우 유용 할 수 있습니다.

IF /I "%1"=="-b" GOTO SPECIFIC

5

문자열을 비교하고 있습니다. 인수가 생략되면 %1공백으로 확장되어 IF =="-b" GOTO SPECIFIC예를 들어 명령이 됩니다 (구문 오류). 문자열을 따옴표 (또는 대괄호)로 묶습니다.

REM this is ok
IF [%1]==[/?] GOTO BLANK

REM I'd recommend using quotes exclusively
IF "%1"=="-b" GOTO SPECIFIC

IF NOT "%1"=="-b" GOTO UNKNOWN

[% 1] == [/?]이 작동하지 않지만 내가 수행하는 경우 [% 1] == [] 또는 "% 1"== ""이면 작동합니다. 어쨌든 이제 갈 수 있습니다. 빠른 응답에 감사드립니다.
javauser71

5

실제로 다른 모든 답변에는 결함이 있습니다. 가장 신뢰할 수있는 방법은 다음과 같습니다.

IF "%~1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

상해:

"%1"=="-b"공백과 따옴표로 인수를 전달 하면을 사용 하면 충돌이 발생합니다. 이것은 가장 신뢰할 수없는 방법입니다.

IF "%1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

C:\> run.bat "a b"

b""=="-b" was unexpected at this time.

[%1]==[-b]공백과 따옴표로 충돌하지 않기 때문에 사용하는 것이 더 좋지만 인수가 따옴표로 묶이면 일치하지 않습니다.

IF [%1]==[-b] (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

C:\> run.bat "-b"

(does not match, and jumps to UNKNOWN instead of SPECIFIC)

사용 "%~1"=="-b"이 가장 신뢰할 수 있습니다. %~1주변 따옴표가 있으면 제거합니다. 따라서 따옴표를 사용하거나 사용하지 않고 인수 없이도 작동합니다.

IF "%~1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

C:\> run.bat
C:\> run.bat -b
C:\> run.bat "-b"
C:\> run.bat "a b"

(all of the above tests work correctly)

1
이것은 대괄호의 끝이 아닙니다 IF [%~1]==[].-이것은 작동하며 심지어 "-b". 당신 은 상자, 음, 정사각형 [대괄호] 안에서 생각할 수 있어야합니다 .
Tomasz Gandor

3

나는 최근에 배치 파일에서 복잡한 매개 변수 스위치를 구현하는 데 어려움을 겪고 있으므로 여기에 내 연구 결과가 있습니다. 제공된 답변 중 어느 것도 완전히 안전하지 않습니다. 예 :

"%1"=="-?" 매개 변수가 따옴표로 묶인 경우 (파일 이름 등에 필요함) 일치하지 않거나 매개 변수가 따옴표로 묶여 있고 공백이있는 경우 (파일 이름에서 자주 표시됨) 충돌이 발생합니다.

@ECHO OFF
SETLOCAL
echo.
echo starting parameter test...
echo.
rem echo First parameter is %1
if "%1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)
C:\>test.bat -?

starting parameter test...

Condition is true, param=-?

C:\>test.bat "-?"

starting parameter test...

Condition is false, param="-?"

대괄호가있는 모든 조합 [%1]==[-?]또는 [%~1]==[-?]매개 변수에 따옴표 안에 공백이있는 경우 실패합니다.

@ECHO OFF
SETLOCAL 
echo.
echo starting parameter test...
echo.
echo First parameter is %1
if [%~1]==[-?] (echo Condition is true, param=%1) else (echo Condition is false, param=%1)

C:\>test.bat "long file name"

starting parameter test...

First parameter is "long file name"
file was unexpected at this time.

제안 된 가장 안전한 솔루션 "%~1"=="-?"은 따옴표 밖에있는 텍스트와 따옴표 안에 공백이있는 텍스트를 포함하는 복잡한 매개 변수와 함께 충돌합니다.

@ECHO OFF
SETLOCAL 
echo.
echo starting parameter test...
echo.
echo First parameter is %1
if "%~1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)

C:\>test.bat -source:"long file name"

starting parameter test...

First parameter is -source:"long file name"
file was unexpected at this time.

위의 모든 시나리오를 다룰 수있는 유일한 방법은 EnableDelayedExpansion 을 사용 하고 변수를 사용하여 값이 아닌 참조로 매개 변수를 전달하는 것입니다. 그러면 가장 복잡한 시나리오도 잘 작동합니다.

@ECHO OFF
SETLOCAL EnableDelayedExpansion
echo.
echo starting parameter test...
echo.
echo First parameter is %1
:: we assign the parameter to a variable to pass by reference with delayed expansion
set "var1=%~1"
echo var1 is !var1!
:: we assign the value to compare with to a second variable to pass by reference with delayed expansion
set "var2=-source:"c:\app images"\image.png"
echo var2 is !var2!
if "!var1!"=="!var2!" (echo Condition is true, param=!var1!) else (echo Condition is false, param=!var1!)
C:\>test.bat -source:"c:\app images"\image.png

starting parameter test...

First parameter is -source:"c:\app images"\image.png
var1 is -source:"c:\app images"\image.png
var2 is -source:"c:\app images"\image.png
Condition is true, param=-source:"c:\app images"\image.png

C:\>test.bat -source:"c:\app images"\image1.png

starting parameter test...

First parameter is -source:"c:\app images"\image1.png
var1 is -source:"c:\app images"\image1.png
var2 is -source:"c:\app images"\image.png
Condition is false, param=-source:"c:\app images"\image1.png

C:\>test.bat -source:"c:\app images\image.png"

starting parameter test...

First parameter is -source:"c:\app images\image.png"
var1 is -source:"c:\app images\image.png"
var2 is -source:"c:\app images"\image.png
Condition is false, param=-source:"c:\app images\image.png"

0

Windows 배치에는이를 수행하기위한 DEFINED 키워드가 있습니다.

IF DEFINED %~1 foo
IF NOT DEFINED %~1 bar

고마워요 데이비드. IF와 IF NOT 사이에 캐리지 리턴과 새 줄이없는 이유를 모르겠습니다. 나는 눈치 채지 못했다.
Charles
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.