Windows command prompt: Using a variable set in the same line of a one-liner

后端 未结 4 1249
别那么骄傲
别那么骄傲 2021-02-13 23:29

Okay, I learned that one can use & or && to combine multiple commands into a single line, but it seems that variables that are set

相关标签:
4条回答
  • 2021-02-13 23:49

    I could not get an IF command to work with either call or cmd /v /c so I would like to offer another option for those who may need it: use FOR /F to declare and use a variable within a single command. For example:

    FOR /F %i IN ('echo 123') DO (IF %i==123 echo done)
    

    The %i is the variable that is set with the result of the IN command, which in this example is 'echo 123'.

    For values with single quotes or spaces, use the "usebackq tokens=*" flag to put the command in backquotes:

    FOR /F "usebackq tokens=*" %i IN (`echo "hello, ' ' world!"`) DO (IF %i=="hello, ' ' world!" echo done)
    
    0 讨论(0)
  • 2021-02-14 00:05

    You can do it in the same line, but I would recommend to use a batch file like preHook.bat.

    As one liner

    set "mu=hello, world!" && call echo %^mu%
    

    At first you can see that the quotes are different than yours.


    Here's why:

    set test1="quotes"
    set "test2=no quotes" with comment
    

    In the first test, the quotes will be part of the test1 variable, as well as all characters after the last quote.

    In the second test, it uses the extended syntax of the SET command.
    So the content will be no quotes, as only the content to the last quote is used; the rest will be dropped.

    To echo the variable content, I use call echo %^mu%, as percent expansion will expand it when the line is parsed, before any of the commands are executed.

    But the call command will be executed later, and it restarts the parser, which, when used at the command line, uses different expansion rules than the batch parser: an empty variable (in this case, %^mu%, in the first time) stays unchanged in the line; but, in the next parser phase, the ^ caret will be removed.

    In your case, call echo %mu% would also work, but only when mu is always empty. The caret variant also works when mu has content before the line is executed.

    More about the parser at SO: How does the Windows Command Interpreter (CMD.EXE) parse scripts? And about variable expansion at SO: Variable expansion

    0 讨论(0)
  • 2021-02-14 00:05

    Though I accepted @jeb's answer, ultimately I had to go another route, because I needed to pipe the output of my command, and doing so on call led to mangled results. Indeed, the documentation for call itself remarks,

    Do not use pipes and redirection symbols with call.

    Instead, reminded by @Blorgbeard of cmd's /v option (and I believe that should be lowercase, not uppercase), I realized I could simply start a subprocess:

    C:\Users\Andrew>cmd /v /c "set foo=hello, world!&& echo !foo!"
    hello, world!
    

    (For some reason, /v must appear before /c.) Within the quotes, I was able pipe my output to other utilities. One tip for those taking this path: If you find yourself needing to use quotes within those quotes, I suggest avoiding them altogether and trying character codes, e.g. \x20 for space, \x22 for double quotes, and so on.

    For example, this was the eventual solution to my problem (warning: may cause eyes to bleed):

    C:\Users\Andrew>cmd /v /c "set source=C:\source& set target=C:\target& set archive=C:\archive& robocopy.exe !source! !target! /l /e /zb /xx /xl /fp /ns /nc /ndl /np /njh /njs | sed -e s/^^[\t\x20]\+// | sed -e /^^$/d | sed -e s/^!source:\=\\!// | sed -e s/.*/xcopy\x20\/Fvikrhyz\x20\x22!source:\=\\!^&\x22\x20\x22!archive:\=\\!^&\x22/"
    
    0 讨论(0)
  • 2021-02-14 00:06

    Try the following:

    cmd.exe /v /c "set foo=hello, world & echo !foo!"
    

    The /v argument enables delayed variable expansion. This allows you to access variables' values at execution time rather than at parse time (the default). You do this by writing !foo! instead of %foo% (with this /v option turned on).

    Instead of passing /v, you can also turn delayed variable expansion on permanently via the registry, which obviously affects the entire system:

    [HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor]
    "DelayedExpansion"= (REG_DWORD)
    1=enabled 0=disabled (default)
    
    0 讨论(0)
提交回复
热议问题