2

How can I put the entire Powershell output into a Batch variable?
Another post has suggested

@for /f "delims=" %%a in ('Powershell -C Get-Content myFile.txt -Raw') do Set "myVar=%%a"

but that only returns the last line.
My end goal is to read a multi-line text file and pass it into another script.

[EDIT] Conclusion: batch is not made for this as variables cannot contain a newline character without obscure tricks, I'm switching to Powershell.

6
  • Each line is being sent to the variable one at a time, what you will therefore see is the last line which was defined. If you really want somebody to assist you with something unrelated to the code you've posted, perhaps you could properly explain to us exactly how you are intending to pass the file's content to another script, and what type of script you're talking about. Commented Aug 3 at 15:05
  • @Compo I have a .bat script someone else made that does search and replace on a text file. I want to replace some text with multiple lines, which are currently in another text file. So I'm trying to read the file and pass it into replacing script as a %variable% Commented Aug 3 at 15:10
  • That makes absolutely no sense to somebody other than you. What we need to know is why you are trying to pass overy single line as one variable to some .bat script, rather than simply asking powershell to perform the replacement directly, or in this script instead. Commented Aug 3 at 15:16
  • 1
    Sorry, but it seems like you are not thinking this through. You are simply trying to replace text with multiple lines of text in a file. This can probably be done directly using Get-Content and Set-Content with PowerShell. There is absolutely no need to involve a batch file for this task, and certainly not the old .bat script written by somebody else. Commented Aug 3 at 16:16
  • 2
    I'm not a fan of "use another language" comments, but in this case you're using PowerShell anyway - go use only PowerShell. It can read files, it can search/replace, it can handle multiline variables and can write files. I'm not fit with PS, but this looks like it can be done with just two lines (one to read the multiline variable from fileB and one to read/replace/write fileA). Commented Aug 3 at 17:11

3 Answers 3

3

An attempt to provide the bigger picture:

  • It is possible to store multiline string values in batch-file variables - and therefore also to read a file's content into a variable with for /f - but the technique for doing so is obscure, cumbersome, and limited to ca. 8,190 characters, excluding an optional trailing newline[1] - see jeb's helpful answer, which builds on an of necessity Byzantine, but robust[2] solution introduced in an earlier answer of his.

  • Therefore, it's best to pass file content to a target script or utility either indirectly, by a file path argument or via stdin (e.g. < myFile.txt or type myFile.txt | ...); of course, the target script or utility must be designed to accept file content this way.

    • If you need to capture multiline output from arbitrary commands in a batch-file variable, you can again use jeb's technique.
  • If feasible, switch to PowerShell altogether, whose scripting language is far superior to that of batch files. Notably, in the case at hand the solution would be as simple as:

    $myVar = Get-Content myFile.txt -Raw
    

[1] The exact limit depends on whether the the file contains a single line only (optionally followed by a trailing newline) or multiple lines: in the single-line case, the limit is 8,144 vs. 8,190 in the multiline case.

[2] There is one edge case that isn't covered: If the input file's last (or only) line contains only a single character and isn't followed by a newline.

Sign up to request clarification or add additional context in comments.

Comments

2

Fundamentally, a batch variable can only contain a single string, so you need to put your data into many variables. There are many ways to do this, documented on SO through thousands of examples.

To devise a way to suit you, we would need to know more about the data that your powersmell application produces.

Two common ways are

FOR /f "tokens=1* delims=:" %b IN ('somecommandwithtextoutput^|findstr /n /R ".*" ""') DO SET "$%b$=%c"&SET /a $0=%b
FOR /f "tokens=1* delims=][" %b IN ('somecommandwithtextoutput^|find /v /n ""') DO SET "$%b$=%c"&SET /a $0=%b

These exploit the delimiters capabilities of for /f by finding and parsing the strings produced. The ^| is an escaped-pipe to deliver the text to the find utility chosen. The first uses /n to prefix the lines found with number: the second with [number]. the set thus produces environment variables named $1=first line $2=second line, etc and $0=line count

The choice of $ is arbitrary - it can be any valid variablename.

set $ 

can be used to display the variables set.

Processing beyon that is another issue completely, and will also involve understanding of the effects of "Poison characters" (those with special meaning to the batch language, such as !%~&^())

4 Comments

A batch variable can only contain a single string - then why can't I simply put all file contents into the variable as a single string, with newline characters as part of the string?
Because the variable cannot contain a newline character-sequence.
While it is both obscure and cumbersome, you can create variables with multiline values (embedded newlines), as demonstrated in jeb's answer. Fundamentally, your answer addresses a different use case than the one in the question: the question is about capturing multiline command output in full in a variable, whereas you're discussing parsing single-line output into substrings.
True, but not for the faint-hearted. If you are very determined then obviously you can use such techniques as Jeb suggests, but I'd view it as more trouble than it's worth. Another possible way would be to string the lines together using a character that would not appear in the text as a separator. The question also arises - why can the the script that is receiving this data not simply read the file myFile.txt itself or even call the succeeding script and have it reconstruct the file from the inherited environment?
2

A batch variable can contain new line characters, but to use it for a search & replace operation is a complex task.

Another limiting factor is that a variable can contain a maximum of 8,191 characters.

Reading a file/command output into a variable can be solved with SO: Assign output of a program to a variable using a MS batch file

@echo off
setlocal

call :initMacro

setlocal EnableDelayedExpansion
%$set% myVar="type myFile.txt"
echo fileContent: !myVar!
exit /b

But this will not solve the complex task of using this for search and replace.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.