سؤال

أحتاج إلى تمرير معرف وكلمة مرور إلى ملف دفعي في وقت التشغيل بدلاً من ترميزهما في الملف.

إليك ما يبدو عليه سطر الأوامر:

test.cmd admin P@55w0rd > test-log.txt
هل كانت مفيدة؟

المحلول 2

وإليك كيف فعلت ذلك:

@fake-command /u %1 /p %2

إليك ما يبدو عليه الأمر:

test.cmd admin P@55w0rd > test-log.txt

ال %1 ينطبق على المعلمة الأولى %2 (وهذا هو الجزء الصعب) ينطبق على الثاني.يمكنك تمرير ما يصل إلى 9 معلمات بهذه الطريقة.

نصائح أخرى

نصيحة أخرى مفيدة هي الاستخدام %* ليعني "الكل".على سبيل المثال:

echo off
set arg1=%1
set arg2=%2
shift
shift
fake-command /u %arg1% /p %arg2% %*

عند تشغيل:

test-command admin password foo bar

سيتم تشغيل الملف الدفعي أعلاه:

fake-command /u admin /p password admin password foo bar

قد يكون بناء الجملة خاطئًا بعض الشيء، لكن هذه هي الفكرة العامة.

إذا كنت تريد التعامل مع المعلمات المفقودة بذكاء، فيمكنك القيام بشيء مثل:

IF %1.==. GOTO No1
IF %2.==. GOTO No2
... do stuff...
GOTO End1

:No1
  ECHO No param 1
GOTO End1
:No2
  ECHO No param 2
GOTO End1

:End1

يمكن أن يكون الوصول إلى معلمات الدفعة أمرًا بسيطًا باستخدام %1 و%2 و...%9 أو أيضًا %*،
ولكن فقط إذا كان المحتوى بسيطًا.

لا توجد طريقة بسيطة للمحتويات المعقدة مثل "&"^&, ، لأنه من غير الممكن الوصول إلى %1 دون حدوث خطأ.

set  var=%1
set "var=%1"
set  var=%~1
set "var=%~1"

تتوسع الخطوط إلى

set  var="&"&
set "var="&"&"
set  var="&"&
set "var="&"&"

ويفشل كل سطر، كواحد من & هو خارج الاقتباسات.

يمكن حلها بالقراءة من ملف مؤقت أ لاحظ نسخة المعلمة

@echo off
SETLOCAL DisableDelayedExpansion

SETLOCAL
for %%a in (1) do (
    set "prompt="
    echo on
    for %%b in (1) do rem * #%1#
    @echo off
) > param.txt
ENDLOCAL

for /F "delims=" %%L in (param.txt) do (
  set "param1=%%L"
)
SETLOCAL EnableDelayedExpansion
set "param1=!param1:*#=!"
set "param1=!param1:~0,-2!"
echo %%1 is '!param1!'

الحيلة هي التمكين echo on وقم بتوسيع %1 بعد أ rem بيان (يعمل أيضًا مع %2 .. %*).
حتى "&"& يمكن تكراره دون إنتاج خطأ، كما هو ملاحظ.

ولكن لتكون قادرًا على إعادة توجيه إخراج ملف echo on, ، أنت بحاجة إلى حلقتين.

الشخصيات الإضافية * # تستخدم لتكون آمنة ضد محتويات مثل /? (سيظهر المساعدة ل REM).
أو يمكن أن تعمل علامة الإقحام ^ الموجودة في نهاية السطر كحرف متعدد الأسطر، حتى بعد الحرف a rem.

ثم قراءة المعلمة ريم الإخراج من الملف، ولكن بعناية.
يجب أن يعمل For /F مع تأخر التوسع ، ومحتويات أخرى مع "!" سيتم تدميرها.
بعد إزالة الأحرف الإضافية في param1, ، لك ذالك.

وللاستخدام param1 بطريقة آمنة، تمكين التوسع المؤجل.

نعم، ولا تنس استخدام متغيرات مثل %%1 عند الاستخدام if و for والعصابة.

إذا نسيت المزدوج %, ، فسوف تقوم باستبدال وسيطات سطر الأوامر (ربما تكون فارغة) وستتلقى بعض رسائل الخطأ المربكة جدًا.

ليست هناك حاجة لتعقيد الأمر.إنه ببساطة أمر %1 %2 معلمات، على سبيل المثال،

@echo off

xcopy %1 %2 /D /E /C /Q /H /R /K /Y /Z

echo copied %1 to %2

pause

يعرض "الإيقاف المؤقت" ما فعله الملف الدفعي وينتظر منك الضغط على أي مفتاح.احفظه باسم xx.bat في مجلد Windows.

لاستخدامه، اكتب على سبيل المثال:

xx c:\f\30\*.* f:\sites\30

يعتني هذا الملف الدفعي بجميع المعلمات الضرورية، مثل نسخ الملفات الأحدث فقط، وما إلى ذلك.لقد استخدمته منذ ما قبل Windows.إذا كنت ترغب في رؤية أسماء الملفات، أثناء نسخها، فاترك ملف Q معامل.

@ECHO OFF
:Loop
IF "%1"=="" GOTO Continue
SHIFT
GOTO Loop
:Continue

ملحوظة:لو "%1"=="" سوف يسبب مشاكل إذا %1 محاط بعلامات الاقتباس نفسها.

في هذه الحالة، استخدم IF [%1]==[] أو، في NT 4 (SP6) والإصدارات الأحدث فقط، IF "%~1"=="" بدلاً من.

كان أحد الأصدقاء يسألني عن هذا الموضوع مؤخرًا، لذا فكرت في نشر كيفية التعامل مع وسيطات سطر الأوامر في الملفات الدفعية.

تحتوي هذه التقنية على القليل من الحمل كما سترون، ولكنها تجعل ملفاتي الدفعية سهلة الفهم وسريعة التنفيذ.وكذلك دعم الهياكل التالية:

>template.bat [-f] [--flag] [/f] [--namedvalue value] arg1 [arg2][arg3][...]

جوهر الأمر هو الحصول على :init, :parse, ، و :main المهام.

استخدام المثال

>template.bat /?
test v1.23
This is a sample batch file template,
providing command-line arguments and flags.

USAGE:
test.bat [flags] "required argument" "optional argument"

/?, --help           shows this help
/v, --version        shows the version
/e, --verbose        shows detailed output
-f, --flag value     specifies a named parameter value

>template.bat          <- throws missing argument error
(same as /?, plus..)
****                                   ****
****    MISSING "REQUIRED ARGUMENT"    ****
****                                   ****

>template.bat -v
1.23

>template.bat --version
test v1.23
This is a sample batch file template,
providing command-line arguments and flags.

>template.bat -e arg1
**** DEBUG IS ON
UnNamedArgument:    "arg1"
UnNamedOptionalArg: not provided
NamedFlag:          not provided

>template.bat --flag "my flag" arg1 arg2
UnNamedArgument:    "arg1"
UnNamedOptionalArg: "arg2"
NamedFlag:          "my flag"

>template.bat --verbose "argument #1" --flag "my flag" second
**** DEBUG IS ON
UnNamedArgument:    "argument #1"
UnNamedOptionalArg: "second"
NamedFlag:          "my flag"

template.bat

@::!/dos/rocks
@echo off
goto :init

:header
    echo %__NAME% v%__VERSION%
    echo This is a sample batch file template,
    echo providing command-line arguments and flags.
    echo.
    goto :eof

:usage
    echo USAGE:
    echo   %__BAT_NAME% [flags] "required argument" "optional argument" 
    echo.
    echo.  /?, --help           shows this help
    echo.  /v, --version        shows the version
    echo.  /e, --verbose        shows detailed output
    echo.  -f, --flag value     specifies a named parameter value
    goto :eof

:version
    if "%~1"=="full" call :header & goto :eof
    echo %__VERSION%
    goto :eof

:missing_argument
    call :header
    call :usage
    echo.
    echo ****                                   ****
    echo ****    MISSING "REQUIRED ARGUMENT"    ****
    echo ****                                   ****
    echo.
    goto :eof

:init
    set "__NAME=%~n0"
    set "__VERSION=1.23"
    set "__YEAR=2017"

    set "__BAT_FILE=%~0"
    set "__BAT_PATH=%~dp0"
    set "__BAT_NAME=%~nx0"

    set "OptHelp="
    set "OptVersion="
    set "OptVerbose="

    set "UnNamedArgument="
    set "UnNamedOptionalArg="
    set "NamedFlag="

:parse
    if "%~1"=="" goto :validate

    if /i "%~1"=="/?"         call :header & call :usage "%~2" & goto :end
    if /i "%~1"=="-?"         call :header & call :usage "%~2" & goto :end
    if /i "%~1"=="--help"     call :header & call :usage "%~2" & goto :end

    if /i "%~1"=="/v"         call :version      & goto :end
    if /i "%~1"=="-v"         call :version      & goto :end
    if /i "%~1"=="--version"  call :version full & goto :end

    if /i "%~1"=="/e"         set "OptVerbose=yes"  & shift & goto :parse
    if /i "%~1"=="-e"         set "OptVerbose=yes"  & shift & goto :parse
    if /i "%~1"=="--verbose"  set "OptVerbose=yes"  & shift & goto :parse

    if /i "%~1"=="--flag"     set "NamedFlag=%~2"   & shift & shift & goto :parse

    if not defined UnNamedArgument     set "UnNamedArgument=%~1"     & shift & goto :parse
    if not defined UnNamedOptionalArg  set "UnNamedOptionalArg=%~1"  & shift & goto :parse

    shift
    goto :parse

:validate
    if not defined UnNamedArgument call :missing_argument & goto :end

:main
    if defined OptVerbose (
        echo **** DEBUG IS ON
    )

    echo UnNamedArgument:    "%UnNamedArgument%"

    if defined UnNamedOptionalArg      echo UnNamedOptionalArg: "%UnNamedOptionalArg%"
    if not defined UnNamedOptionalArg  echo UnNamedOptionalArg: not provided

    if defined NamedFlag               echo NamedFlag:          "%NamedFlag%"
    if not defined NamedFlag           echo NamedFlag:          not provided

:end
    call :cleanup
    exit /B

:cleanup
    REM The cleanup function is only really necessary if you
    REM are _not_ using SETLOCAL.
    set "__NAME="
    set "__VERSION="
    set "__YEAR="

    set "__BAT_FILE="
    set "__BAT_PATH="
    set "__BAT_NAME="

    set "OptHelp="
    set "OptVersion="
    set "OptVerbose="

    set "UnNamedArgument="
    set "UnNamedArgument2="
    set "NamedFlag="

    goto :eof

دعونا نبقي هذا بسيطا.

هنا ملف .cmd.

@echo off
rem this file is named echo_3params.cmd
echo %1
echo %2
echo %3
set v1=%1
set v2=%2
set v3=%3
echo v1 equals %v1%
echo v2 equals %v2%
echo v3 equals %v3%

فيما يلي 3 مكالمات من سطر الأوامر.

C:\Users\joeco>echo_3params 1abc 2 def  3 ghi
1abc
2
def
v1 equals 1abc
v2 equals 2
v3 equals def

C:\Users\joeco>echo_3params 1abc "2 def"  "3 ghi"
1abc
"2 def"
"3 ghi"
v1 equals 1abc
v2 equals "2 def"
v3 equals "3 ghi"

C:\Users\joeco>echo_3params 1abc '2 def'  "3 ghi"
1abc
'2
def'
v1 equals 1abc
v2 equals '2
v3 equals def'

C:\Users\joeco>
FOR %%A IN (%*) DO (
    REM Now your batch file handles %%A instead of %1
    REM No need to use SHIFT anymore.
    ECHO %%A
)

يتكرر هذا فوق المعلمات الدفعية (%*) سواء تم اقتباسها أم لا، ثم يردد صدى كل معلمة.

لقد كتبت نصًا بسيطًا read_params يمكن استدعاؤه كدالة (أو خارجية .bat) وسوف يضع كافة المتغيرات في البيئة الحالية.لن يقوم بتعديل المعلمات الأصلية لأن الوظيفة قيد التشغيل callإد مع نسخة من المعلمات الأصلية.

على سبيل المثال، بالنظر إلى الأمر التالي:

myscript.bat some -random=43 extra -greeting="hello world" fluff

myscript.bat سيكون قادرًا على استخدام المتغيرات بعد استدعاء الوظيفة:

call :read_params %*

echo %random%
echo %greeting%

ها هي الوظيفة:

:read_params
if not %1/==/ (
    if not "%__var%"=="" (
        if not "%__var:~0,1%"=="-" (
            endlocal
            goto read_params
        )
        endlocal & set %__var:~1%=%~1
    ) else (
        setlocal & set __var=%~1
    )
    shift
    goto read_params
)
exit /B

محددات

  • لا يمكن تحميل الوسائط بدون قيمة مثل -force.يمكنك استخدام -force=true لكن لا يمكنني التفكير في طريقة للسماح بالقيم الفارغة دون معرفة قائمة المعلمات مسبقًا والتي لن يكون لها قيمة.

سجل التغيير

  • 2/18/2016
    • لم يعد يتطلب التوسع المؤجل
    • يعمل الآن مع وسائط سطر الأوامر الأخرى من خلال البحث عن - قبل المعلمات

للإشارة إلى متغير مجموعة في سطر الأوامر سوف تحتاج إلى استخدامه %a% لذلك على سبيل المثال:

set a=100 
echo %a%  
rem output = 100 

ملحوظة:هذا يعمل لنظام التشغيل Windows 7 pro.

قم بإنشاء ملف دفعي جديد (على سبيل المثال:openclass.bat) واكتب هذا السطر في الملف:

java %~n1

ثم ضع الملف الدفعي في مجلد system32، على سبيل المثال، وانتقل إلى ملف فئة Java الخاص بك، وانقر بزر الماوس الأيمن فوق خصائص، ثم افتح باستخدام...، ثم ابحث عن الملف الدفعي الخاص بك، وحدده وهذا كل ما في الأمر...

إنه يعمل بالنسبة لي.

ملاحظة:لا يمكنني العثور على طريقة لإغلاق نافذة cmd عندما أغلق فئة Java.في الوقت الراهن...

مستوحاة من الإجابة في مكان آخر بواسطةJon، قمت بتصميم خوارزمية أكثر عمومية لاستخراج المعلمات المسماة والقيم الاختيارية والمفاتيح.

لنفترض أننا نريد تنفيذ أداة مساعدة foobar.يتطلب الأمر الأولي.لديها معلمة اختيارية --foo الذي يأخذ خياري القيمة (والتي لا يمكن أن تكون معلمة أخرى بالطبع)؛إذا كانت القيمة مفقودة، فسيتم تعيينها بشكل افتراضي default.كما أن لديها معلمة اختيارية --bar الذي يأخذ أ مطلوب قيمة.وأخيرا يمكن أن يستغرق العلم --baz مع عدم السماح بأي قيمة.أوه، ويمكن أن تأتي هذه المعلمات بأي ترتيب.

وبعبارة أخرى، يبدو الأمر كما يلي:

foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]

هنا الحل:

@ECHO OFF
SETLOCAL
REM FooBar parameter demo
REM By Garret Wilson

SET CMD=%~1

IF "%CMD%" == "" (
  GOTO usage
)
SET FOO=
SET DEFAULT_FOO=default
SET BAR=
SET BAZ=

SHIFT
:args
SET PARAM=%~1
SET ARG=%~2
IF "%PARAM%" == "--foo" (
  SHIFT
  IF NOT "%ARG%" == "" (
    IF NOT "%ARG:~0,2%" == "--" (
      SET FOO=%ARG%
      SHIFT
    ) ELSE (
      SET FOO=%DEFAULT_FOO%
    )
  ) ELSE (
    SET FOO=%DEFAULT_FOO%
  )
) ELSE IF "%PARAM%" == "--bar" (
  SHIFT
  IF NOT "%ARG%" == "" (
    SET BAR=%ARG%
    SHIFT
  ) ELSE (
    ECHO Missing bar value. 1>&2
    ECHO:
    GOTO usage
  )
) ELSE IF "%PARAM%" == "--baz" (
  SHIFT
  SET BAZ=true
) ELSE IF "%PARAM%" == "" (
  GOTO endargs
) ELSE (
  ECHO Unrecognized option %1. 1>&2
  ECHO:
  GOTO usage
)
GOTO args
:endargs

ECHO Command: %CMD%
IF NOT "%FOO%" == "" (
  ECHO Foo: %FOO%
)
IF NOT "%BAR%" == "" (
  ECHO Bar: %BAR%
)
IF "%BAZ%" == "true" (
  ECHO Baz
)

REM TODO do something with FOO, BAR, and/or BAZ
GOTO :eof

:usage
ECHO FooBar
ECHO Usage: foobar ^<command^> [--foo [^<fooval^>]] [--bar ^<barval^>] [--baz]
EXIT /B 1
  • يستخدم SETLOCAL حتى لا تهرب المتغيرات إلى بيئة الاستدعاء.
  • لا تنس تهيئة المتغيرات SET FOO=, ، إلخ.في حالة قيام شخص ما بتعريفهم في بيئة الاتصال.
  • يستخدم %~1 لإزالة الاقتباسات.
  • يستخدم IF "%ARG%" == "" و لا IF [%ARG%] == [] لأن [ و ] لا تلعب مطلقًا بالقيم التي تنتهي بمسافة.
  • حتى لو كنت SHIFT داخل IF كتلة، الحجج الحالية مثل %~1 لا يتم تحديثها لأنها تحدد متى IF يتم تحليلها.يمكنك استخدام %~1 و %~2 داخل IF كتلة، ولكن سيكون الأمر مربكا لأنه كان لديك SHIFT.يمكنك وضع SHIFT في نهاية الكتلة من أجل الوضوح، ولكن هذا قد يضيع و/أو يربك الناس أيضًا.لذلك "التقاط" %~1 و %~1 يبدو أن خارج الكتلة هو الأفضل.
  • لا تريد استخدام معلمة بدلاً من القيمة الاختيارية لمعلمة أخرى، لذلك عليك التحقق IF NOT "%ARG:~0,2%" == "--".
  • كن حذرا فقط ل SHIFT عندما انت يستخدم واحدة من المعلمات.
  • الكود المكرر SET FOO=%DEFAULT_FOO% أمر مؤسف، ولكن البديل سيكون إضافة IF "%FOO%" == "" SET FOO=%DEFAULT_FOO% خارج IF NOT "%ARG%" == "" حاجز.ولكن لأن هذا لا يزال داخل IF "%PARAM%" == "--foo" كتلة، %FOO% سيتم تقييم القيمة وتعيينها قبل أن تدخل الكتلة، لذلك لن تكتشف ذلك أبدًا كلاهما ال --foo المعلمة كانت حاضرة و أيضا أن %FOO% كانت القيمة مفقودة.
  • لاحظ أن ECHO Missing bar value. 1>&2 يرسل رسالة الخطأ إلى stderr.
  • هل تريد سطرًا فارغًا في ملف دفعي لنظام Windows؟عليك أن تستخدم ECHO: أو أحد الاختلافات.

حل بسيط (على الرغم من أن السؤال قديم)

اختبار1.بات

echo off
echo "Batch started"
set arg1=%1
echo "arg1 is %arg1%"
echo on
pause

CallTest1.bat

call "C:\Temp\Test1.bat" pass123

انتاج

YourLocalPath>call "C:\Temp\test.bat" pass123

YourLocalPath>echo off
"Batch started"
"arg1 is pass123"

YourLocalPath>pause
Press any key to continue . . .

حيث YourLocalPath هو مسار الدليل الحالي.

لتبسيط الأمور، قم بتخزين معلمة الأمر في المتغير واستخدم المتغير للمقارنة.

ليس من السهل كتابته فحسب، بل من السهل صيانته أيضًا، لذا إذا قرأت لاحقًا شخصًا آخر أو قرأت النص الخاص بك بعد فترة طويلة من الوقت، فسيكون من السهل فهمه وصيانته.

لكتابة الكود في السطر:انظر الإجابات الأخرى.

enter image description here

لاستخدام التكرار، احصل على جميع الوسائط دفعة واحدة:

@echo off && setlocal EnableDelayedExpansion

 set "_cnt=0" && for %%Z in (%*) do ( 
 set "_arg_=%%Z" && set /a "_cnt=!_cnt! + 1" && set "_arg_[!_cnt!]=!_arg_!"
 shift && for /l %%l in (!_cnt! 1 !_cnt!) do echo/ The argument n:%%l is: !_arg_[%%l]!
 )

goto :eof 

الكود الخاص بك جاهز للقيام بشيء ما برقم الوسيطة حيث يحتاج، مثل...

 @echo off && setlocal EnableDelayedExpansion

 set "_cnt=0" && for %%Z in (%*) do ( 
 set "_arg_=%%Z" && set /a "_cnt=!_cnt! + 1" && set "_arg_[!_cnt!]=!_arg_!"
 shift 

 )

 fake-command /u !_arg_[1]! /p !_arg_[2]! > test-log.txt
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top