windows شرح كيف يمكنني تمرير معلمات سطر الأوامر إلى ملف دفعي؟




batch file شرح (11)

صحيح ، ولا تنسَ استخدام المتغيرات مثل %%1 عند استخدام if and for and the gang.

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

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

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

test.cmd admin [email protected] > test-log.txt

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

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

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

وجوهره هو وجود :init و :parse parse و :main functions.

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

>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

يمكن أن يكون الوصول إلى معلمات الدُفعة أمرًا بسيطًا مع٪ 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).
أو حرف الإقحام ^ at line end يمكن أن يعمل كحرف متعدد الأسطر ، حتى في بعد الحرف.

ثم قراءة إخراج المعلمة rem من الملف ، ولكن بعناية.
يجب أن تعمل FOR / F مع التمديد المتأخر ، وإلا محتويات مع "!" سيتم تدميرها.
بعد إزالة الأحرف الزائدة في param1 ، حصلت عليه.

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


للإشارة إلى متغير مجموعة في سطر الأوامر ، ستحتاج إلى استخدام "٪ a٪" على سبيل المثال:

      set a=100 
      echo %a%  
      output = 100 

ملاحظة: هذا يعمل لـ Windows 7 pro.


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

java %~n1

ثم ضع الملف الدفعي في ، لنقل ، المجلد System32 ، انتقل إلى ملف فئة Java ، انقر بزر الماوس الأيمن ، Properties ، Open with ... ، ثم ابحث عن ملف الدُفعات ، حدده ، وهذا هو ...

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

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


وإليك كيف أفعل ذلك.

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

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

test.cmd admin [email protected] > test-log.txt

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


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

هذه الحلقات عبر المعلمات الدُفعة (٪ *) إما أنها مقتبسة أم لا ، ثم صدى كل معلمة.


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

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 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

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

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

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


دعونا نحافظ على هذا بسيط.

هذا هو ملف .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>




cmd