2

I've got a problem with redirecting input from a file into set/p

Here is my script:

@echo off
echo Reading: {%1}
type %1
echo(
echo Starting...
set VAR=
set /P VAR=<%1
echo VAR is {%VAR%}...

I've read elsewhere (https://stackoverflow.com/a/7827243) that the syntax I am using will work. It does not!

Here is my output:

Reading: {Fruit.txt}
Pears
Apples
Oranges
Kiwi
Grapes
Kumquat

Starting...
VAR is { ■P}...

So - What gives?

Community
  • 1
  • 1

3 Answers3

5

Your file is in Unicode (UTF16) format, and SET /P does not work with Unicode. The TYPE command does work with Unicode, and it converts the output to ANSI. You can redirect the output of TYPE to a new text file, and then your SET /P will work.

@echo off
type %1>new.txt
set VAR=
set /P VAR=<new.txt
echo VAR is {%VAR%}...

EDIT

To get the second line instead of the first:

@echo off
type %1>new.txt
<new.txt (
  set /P VAR=
  set VAR=
  set /P VAR=
)
echo VAR is {%VAR%}...
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • ...or use a single for /f in combination with type, as I suggested. Seems more straightforward to me... – Bill_Stewart Mar 17 '13 at 22:43
  • @AbqBill - This solution is more efficient if the OP only wants the first line. FOR /F is more straight forward if reading the entire file. FOR /F and SET /P each have their advantages and disadvantages when reading a file. Also, your answer does not explain why the OP's original code does not work. – dbenham Mar 17 '13 at 23:13
  • I actually want the 2nd line of the file... Was trying to create the most efficient & robust method - stumbled onto a similar question on this forum & was trying to adapt it to my purpose - but it did not work. So, I simplified & it still did not work - that is why I reached out to yuns guys! – user2178417 Mar 20 '13 at 04:11
  • @user2178417 - I created a Unicode file and replicated your results. I've updated the answer to show how to get the 2nd line. – dbenham Mar 20 '13 at 10:12
  • This should work but the drawback is the need to write out a separate file (to account for encoding). This solution also doesn't account for special shell characters in the input file (e.g., <, >, |). See my second answer for how to work around these drawbacks. – Bill_Stewart Mar 20 '13 at 15:05
1

If the purpose is to read lines of text from a file, why do you need the set /p command?

for /f "delims=" %%a in ('type "file name.txt"') do echo %%a

If you type the command at the cmd.exe command line, you would write %a (one % symbol) rather than %%a (i.e., double the % symbol when using in a shell script [batch file]).

Bill

Bill_Stewart
  • 22,916
  • 4
  • 51
  • 62
  • 1
    The OP's file has UTF16 content. This solutions works because the TYPE command will convert the file contents to ANSI. FOR /F cannot read the contents of a Unicode file directly. – dbenham Mar 17 '13 at 04:34
  • Yeah, as I said I really need the second line, so I guess that I have to write a nested for loop to pick it off. I was hoping for a one- or two-liner to accomplish this task! Here was my original inspiration: http://stackoverflow.com/a/5523806/2178417 – user2178417 Mar 20 '13 at 04:17
  • You can get the second line using my other answer without a need to worry about the encoding (as long as the type command displays the file correctly). Just replace 'if !CURRLINE! EQU 1' with 'if !CURRLINE! EQU 2'. Also, take care that your input file doesn't contain special shell characters (e.g., <, >, |, etc.). – Bill_Stewart Mar 20 '13 at 15:02
0

Here's another technique for reading only the first line of a file using for /f and type that doesn't rely on set /p:

@echo off
setlocal enableextensions enabledelayedexpansion
set VAR=
set CURRLINE=0
for /f "delims=" %%a in ('type "test.txt"') do (
  set /a CURRLINE+=1
  if !CURRLINE! EQU 1 (
    set VAR=%%a
    goto :DONE
  )
)
:DONE
echo %VAR%
endlocal

The advantage here is there's no need to write out a separate file.

However, note that either of these approaches (set /p or for /f with type) will have problems with special shell characters in the input file (<, >, |, etc.). To get around this problem, one could use a small utility I wrote a while back called shellesc.exe (http://www.westmesatech.com/sst.html) to "escape" the special characters. But if you use these tools, then you can also use linex.exe to pick the line you want and get the result with a little bit less code:

@echo off
setlocal enableextensions
set VAR=
for /f "delims=" %%a in ('type "test.txt" ^| linex -l 1 ^| shellesc') do set VAR=%%a
echo %VAR%
endlocal

Note that this approach has the additional advantage of not "choking" on special shell characters (shellesc).

HTH,

Bill

Bill_Stewart
  • 22,916
  • 4
  • 51
  • 62