كيف يمكنني تمرير الوسائط إلى ملف دفعي؟
-
09-06-2019 - |
سؤال
أحتاج إلى تمرير معرف وكلمة مرور إلى ملف دفعي في وقت التشغيل بدلاً من ترميزهما في الملف.
إليك ما يبدو عليه سطر الأوامر:
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 هو مسار الدليل الحالي.
لتبسيط الأمور، قم بتخزين معلمة الأمر في المتغير واستخدم المتغير للمقارنة.
ليس من السهل كتابته فحسب، بل من السهل صيانته أيضًا، لذا إذا قرأت لاحقًا شخصًا آخر أو قرأت النص الخاص بك بعد فترة طويلة من الوقت، فسيكون من السهل فهمه وصيانته.
لكتابة الكود في السطر:انظر الإجابات الأخرى.
لاستخدام التكرار، احصل على جميع الوسائط دفعة واحدة:
@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