Windows XP batch file concat

后端 未结 4 1494
囚心锁ツ
囚心锁ツ 2021-01-03 17:25

I\'m trying to accomplish the following ridiculous task:

I have a text file containing a set of fully qualified filesnames. I want to iterate through the file and app

4条回答
  •  一整个雨季
    2021-01-03 17:55

    As for references, SS64.com isn't bad. Rob van der Woude gets linked fairly often, too.


    As for your problem, that's easy:

    @echo off
    setlocal enableextensions enabledelayedexpansion
    
    set LIST=
    for /f %%x in (yourfile.txt) do (
        set LIST=!LIST! "%%x"
    )
    
    echo %LIST%
    
    endlocal
    

    More in-depth explanation:

    setlocal enableextensions enabledelayedexpansion
    

    We're enabling delayed expansion here. This is crucial as otherwise we wouldn't be able to manipulate the list of files within the for loop that follows.

    for /f %%x in (yourfile.txt) do (
        set LIST=!LIST! "%%x"
    )
    

    for /f iterates over lines in a file, so exactly what we need here. In each loop iteration we append the next line to the LIST variable. Note the use of !LIST! instead of the usual %LIST%. This signals delayed expansion and ensures that the variable gets re-evaluated every time this command is run.

    Usually cmd expands variables to their values as soon as a line is read and parsed. For cmd a single line is either a line or everything that counts as a line, which happens to hold true for blocks delimited by parentheses like the one we used here. So for cmd the complete block is a single statement which gets read and parsed once, regardless of how often the interior of the loop runs.

    If we would have used %LIST% here instead of !LIST! then the variable would have been replaced immediately by its value (empty at that point) and the loop would have looked like this:

    for /f %%x in (yourfile.txt) do (
        set LIST= "%%x"
    )
    

    Clearly this isn't what we wanted. Delayed expansion makes sure that a variable is expanded only when its value is really needed. In this case when the interior of the loop runs and constructs a list of file names.

    Afterwards the variable %LIST% or !LIST! (now it doesn't really matter anymore which to use) contains the list of lines from the file.

    Funnily enough, the help for the set command includes exactly this example for delayed expansion:

    Finally, support for delayed environment variable expansion has been added. This support is always disabled by default, but may be enabled/disabled via the /V command line switch to CMD.EXE. See CMD /?

    Delayed environment variable expansion is useful for getting around the limitations of the current expansion which happens when a line of text is read, not when it is executed. The following example demonstrates the problem with immediate variable expansion:

    set VAR=before
    if "%VAR%" == "before" (
        set VAR=after
        if "%VAR%" == "after" @echo If you see this, it worked
    )
    

    would never display the message, since the %VAR% in BOTH IF statements is substituted when the first IF statement is read, since it logically includes the body of the IF, which is a compound statement. So the IF inside the compound statement is really comparing "before" with "after" which will never be equal. Similarly, the following example will not work as expected:

    set LIST=
    for %i in (*) do set LIST=%LIST% %i
    echo %LIST%
    

    in that it will NOT build up a list of files in the current directory, but instead will just set the LIST variable to the last file found. Again, this is because the %LIST% is expanded just once when the FOR statement is read, and at that time the LIST variable is empty. So the actual FOR loop we are executing is:

    for %i in (*) do set LIST= %i
    

    which just keeps setting LIST to the last file found.

    Delayed environment variable expansion allows you to use a different character (the exclamation mark) to expand environment variables at execution time. If delayed variable expansion is enabled, the above examples could be written as follows to work as intended:

    set VAR=before
    if "%VAR%" == "before" (
        set VAR=after
        if "!VAR!" == "after" @echo If you see this, it worked
    )
    
    set LIST=
    for %i in (*) do set LIST=!LIST! %i
    echo %LIST%
    

提交回复
热议问题