Setting a variable from an entire txt file

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
julesverne
Posts: 81
Joined: 19 Nov 2013 00:41

Setting a variable from an entire txt file

#1 Post by julesverne » 27 Nov 2013 04:30

Hi all,

Another problem that has my head scratching, I don't even know if it's possible.

For a batch file or from cmdline.

Can you set 1 variable from an entire txt file, similar as SOLVED here on stackoverflow: http://stackoverflow.com/questions/134001/how-can-i-load-the-contents-of-a-text-file-into-a-batch-file-variable with the difference being.. keeping all lines separated as they are in the txt file. Keeping in mind that no idea what the first or last character in each line is or how many spaces in each line.

For example:

test.txt looks like this:

Hi here is some text
This is another line of text -
This is a third line of text 9$

possible variable like this:

set var1= (
Hi here is some text
This is another line of text -
This is a third line of text 9$
)

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Setting a variable from an entire txt file

#2 Post by foxidrive » 27 Nov 2013 07:13

Not with the CRLF between each line, without adding them again in some manner.

Why do you need to do this? The answer to that will help to find a solution.

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Setting a variable from an entire txt file

#3 Post by penpen » 27 Nov 2013 13:49

I see it in a similar way as foxidrive.
But if you can't avoid it, this is a solution adding the LF only between the lines:

Code: Select all

@echo off
cls
set LF=^


set ^"\n=^%LF%%LF%^%LF%"
setlocal enableDelayedExpansion
set "var1= ("
for /F "tokens=* usebackq delims=" %%a in ("test.txt") do (
   set "var1=!var1!!\n!%%a"
)
set "var1=!var1!!\n!)"
set var1
endlocal

penpen

Aacini
Expert
Posts: 1927
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Setting a variable from an entire txt file

#4 Post by Aacini » 27 Nov 2013 17:23

Another solution is to use an array and store each line in an element:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set numLines=0
for /F "usebackq delims=" %%a in ("test.txt") do (
   set /A numLines+=1
   set "line[!numLines!]=%%a"
)


This way you do not need to search for individual lines for a posterior processing, because they are separated indeed.

Antonio

Magialisk
Posts: 104
Joined: 25 Jul 2013 19:00

Re: Setting a variable from an entire txt file

#5 Post by Magialisk » 27 Nov 2013 18:50

Antonio beat me to it. I've used an array technique to hold lines of a file in "one" variable before and it worked well enough for me. Easy to iterate over or later extract "line 7" for example, but its not explicitly what you asked for.

Like penpen and foxidrive mentioned, if you spell out what problem you're trying to solve there might be a better way to solve it.

julesverne
Posts: 81
Joined: 19 Nov 2013 00:41

Re: Setting a variable from an entire txt file

#6 Post by julesverne » 27 Nov 2013 19:10

Thanks for the replies everyone. Aacini, I thought about it at first and didn't want to do an array, however, rethinking about it, it could become useful. And penpen, I haven't tried it yet, but will. But I'd like to first answer foxidrive.

foxidrive
Why do you need to do this? The answer to that will help to find a solution.


Since, I've finally got the contribution forum bug, I'll finally give a small bit of an introduction of myself, in order to answer your question. I've been writing bat scripts for myself and my job. It took awhile, but I'm finally getting the hang of it, and now I've really got a nerdy passion for it. When I create them for my job however, I really try to dumb it down. I've created menu's or really have it as hands off as possible for my coworkers who really don't have the time nor desire to understand the inner workings. That being said, I want to eventually learn visual basic and python so it's more GUI based instead of CMD as the window. Until then, I had an idea, one which has been brought up before in this forum, and one that was shut down pretty quickly as bad programming. Which I get. However, this is an instance where I'd like to do that, so my coworkers can have something a little bit better to look at.

So.. to answer your question.. I want to take the output of ffprobe.exe (which is ffmpeg a video/audio command line tool for those who don't know), and output it into a msgbox made by vbs rather than windows CMD. I don't know vbs at all, other than creating simple message boxes. So originally I was just going to make a bat file, run ffmprobe, and output the info to a txt file, get the entire output of the txt file as 1 variable, and use that and echo out a vbs file using that variable. One of the issues I'd have to deal with of course is how many characters and/or lines a msgbox can contain. I believe it's only a 1000 or around there, so getting rid of some of that verbose info might help, hence why aacini's suggestion might be helpful.

Currently, I stick my bat file in the "send to" folder. So someone can simply right click on a video or audio file, select the bat file from the "send to" and get the information of the file.

This is my current bat file:

Code: Select all

@echo off

title Multi Media File Information

For %%i in (%*) do (

title MultiMedia File Information %%i

C:\ffmpeg\ffmpeg\bin\ffprobe.exe -i %%i

)

pause


For those unfamiliar with FFMPEG it puts all of its text output to stderr, rather than stdout. It does this so that you can pipe the encoder output to other programs. So I've piped output to a txt file like this

Code: Select all

C:\ffmpeg\ffmpeg\bin\ffprobe.exe -i %%i > videoinfo.txt 2>&1
.. and this is where aacini's array idea actually made me realize doing it this way I could also get rid of some of the unnecessary verbose output.

So, that's what I got. Just trying to prettify a program for the coworkers and learn a little in the process.

I'm open to ideas on how to do this. If someone knows Visual Basic and can do the code without bat... I'm cool with that too, but I wouldn't have any input as I've said before, I don't know how. But would love to see it as I know it would help me understand it a bit better.

Thanks in advance for any help/suggestions!

Jules

Squashman
Expert
Posts: 4488
Joined: 23 Dec 2011 13:59

Re: Setting a variable from an entire txt file

#7 Post by Squashman » 27 Nov 2013 21:19

I have found out from past experience that dumbing it down normally makes the user even more ignorant to the point that they think that because the script can do one thing it should be able to do something similar or they use it for a task it was not inteneded for and they wonder why it does not work.

Magialisk
Posts: 104
Joined: 25 Jul 2013 19:00

Re: Setting a variable from an entire txt file

#8 Post by Magialisk » 27 Nov 2013 23:26

julesverne wrote:I've been writing bat scripts for myself and my job. It took awhile, but I'm finally getting the hang of it, and now I've really got a nerdy passion for it. When I create them for my job however, I really try to dumb it down.

Squashman wrote:I have found out from past experience that dumbing it down normally makes the user even more ignorant to the point that they think that because the script can do one thing it should be able to do something similar or they use it for a task it was not inteneded for and they wonder why it does not work.

I couldn't agree with the both of you more. The main reason I got into writing batch scripts at all was for work. My pride and joy is a couple of huge batch scripts that do automated disk drive testing and diagnostics. We used to have these long test procedures where the users had to follow all the instructions just right to set up and run tests, then look through the output for the right data, it was a real pain. Over the last 2-3 years I've completely automated everything about disk testing where I work. The BAT scans the system, detects any and all connected drives, sorts them into types (ie: ATA, SATA, SAS, SCSI), determines HDD or SSD, determines the manufacturer (required to parse proprietary SMART data), performs appropriate diagnostics based on all the above, dynamically configures and runs I/O tests using 3rd party software, validates the I/O results, etc. all completely automated.

The issues that come about are two-fold:
1.) I've never met another living breathing human being that understands CMD batch language. Sure there's all the folks at the forum here, but I've never met any of you so I stand by that statement :D In other words, even though my script has easily as many lines or more of comments as it does code (I literally have 2-3 lines of comment describing what "SETLOCAL ENABLEDELAYEDEXPANSION" does, and one more for "@echo off"), it's completely unmaintainable by anyone I work with.
2.) The script works so well, people just assume it can do anything. Sure there's been many bugs, and I'm on something like version 4.4 over the last several years, but in general you double click it, press Enter about 3 times, and come back in a couple hours to print out result logs - users love it. That said I can't tell you how many messages and comments there are stating various limitations such as "you can't run diagnostics on a drive behind a RAID controller", even live warnings as you're running the script and it suspects you've asked it to do something it cant, but people just click through and hope for the best... Once you've given them the cookie, it's your fault they don't have any milk. :evil:

Ah well, that's my rant for the evening, best of luck with your FFMPEG bat. It sounds like you generally have it at the point you need it, and a VBS would just be icing on the cake? I'd offer to help but I too know zero VBS...

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Setting a variable from an entire txt file

#9 Post by foxidrive » 28 Nov 2013 02:46

The help for msgbox states:

prompt
String expression displayed as the message in the dialog box. The maximum length of prompt is approximately 1024 characters, depending on the width of the characters used. If prompt consists of more than one line, you can separate the lines using a carriage return character (Chr(13)), a linefeed character (Chr(10)), or carriage return–linefeed character combination (Chr(13) & Chr(10)) between each line.


So you can use the technique shown above by penpen to add LF in the variable.

jeb
Expert
Posts: 1059
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Setting a variable from an entire txt file

#10 Post by jeb » 28 Nov 2013 04:26

I extend the solution of penpen a bit, so it could also handle empty lines and lines with exclamation marks and carets.
This should be able to load any file up to ~8190 characters.

Code: Select all

@echo off
setlocal EnableDelayedExpansion
set LF=^


REM ** Two empty lines are required
setlocal EnableDelayedExpansion

call :readFile fileContent test.txt
echo !fileContent!
exit /b

:readFile
setlocal DisableDelayedExpansion
set "text="
for /F "delims=" %%L in ('findstr /n "^" "%~2"') do (
   set "line=%%L"
   setlocal EnableDelayedExpansion
   set "line=!line:\=\S!"
   set "line=!line:*:=!"
   for /F "delims=" %%T in (""!text!!line!\n"") do (
     endlocal
     set "text=%%~T"
   )
)
setlocal EnableDelayedExpansion
set "text=!text:"=""!"
set "text=!text:^=^^^^!"
set "text=%text:!=^^^!%" !
set "text=!text:""="!"
for %%L in ("!LF!") DO (
   for /F "delims=" %%T in (""!text!"") do (
     endlocal
     endlocal
     set "%~1=%%~T"
     set "%~1=!%~1:\n=%%~L!"
     set "%~1=!%~1:\S=\!"
   )
)
exit /b

julesverne
Posts: 81
Joined: 19 Nov 2013 00:41

Re: Setting a variable from an entire txt file

#11 Post by julesverne » 28 Nov 2013 22:48

Ok. So finally all my American Thanksgiving festivities have subsided I can return to testing things out. I tried jeb's code and have come to the conclusion between this and another thread here that I'm beginning to think that I program bat files differently than other people do. More to the point, I've taught myself and taught myself the wrong way to do things, because I figured after a year and a half of doing it, I could look at the code and understand it, and therefore understand how to run it or implement it into my batch program. But nope. I have no clue. I'm frustrated with myself for thinking I was getting the hang of it, only to find out.. nope. I really don't know anything.

Sorry, to be specific I changed the test.txt in the bat code to my file name videoinfo.txt. I then simply double clicked on the bat file. With the txt file in the same folder. It just fails as soon as I run it.

julesverne
Posts: 81
Joined: 19 Nov 2013 00:41

Re: Setting a variable from an entire txt file

#12 Post by julesverne » 28 Nov 2013 22:59

Doh! Never mind. It was working. I just had to include a pause to at least show it on the screen. <---- amateur hour. Works great guys! Thank you!


julesverne
Posts: 81
Joined: 19 Nov 2013 00:41

Re: Setting a variable from an entire txt file

#14 Post by julesverne » 29 Nov 2013 18:54

Ok. Decided to go with Jeb's approach and it works great so far and seems really fast. I modified several things which I've pointed out in the code. However, 1 more bit of icing on the cake to complete this is sending errors to a msgbox. I'll explain after the code below.


Code: Select all

@echo on
if not "%minimized%"=="" goto :minimized
set minimized=true
start /min cmd /C ""%~dpnx0" %*"
goto :EOF
:minimized
rem Anything after here will run in a minimized window
REM http://danrice.net/articles/run-a-batch-script-minimized

:startprocess

For %%i in (%*) do (

title MultiMedia File Information %%i

REM RUN FFMPEG AND SEND INFO TO TXT FILE
C:\ffmpeg\ffmpeg\bin\ffprobe.exe -i %%i > "videoinfo.txt" 2>&1

REM THIS WILL FIND THE LINE IN THE TXT FILE THAT STARTS WITH THE WORD INPUT. WANT TO ACTUALLY START ON THE LINE AFTER THAT, WHICH CHANGES WITH EVERY TXT FILE CREATED, BUT THE LINE BEFORE IT IS CONSISTENT
setlocal enabledelayedexpansion
for /f "tokens=*" %%a in ('findstr /n "Input" "videoinfo.txt"') do (
  set FullLine=%%a
  set "FullLine=!FullLine:~0,2!"
  set /a "FullLine+=1
)


REM NEXT TWO LINES OF CODE REMOVE THE FIRST X number of LINES OF THE TEXT FILE
REM http://stackoverflow.com/questions/11428692/batch-file-to-delete-first-3-lines-of-a-text-file/11432438#11432438

more /E +!FullLine! "videoinfo.txt" > "videoinfo.txt.new"
move /y "videoinfo.txt.new" "videoinfo.txt" >nul


REM THIS PART OF THE CODE READS LINES OF THE TEXT FILE AND SETS ALL LINES TO ONE VARIABLE
REM http://www.dostips.com/forum/viewtopic.php?f=3&t=5122#p30226
setlocal EnableDelayedExpansion
set LF=^


REM ** Two empty lines are required
setlocal EnableDelayedExpansion

call :readFile fileContent videoinfo.txt

set /a variable12=0
REM THE LINE BELOW IS MODIFIED SUCH THAT IF THE VIDEOFILE.TXT IS EMPTY THEN SET A VARIABLE TO TRUE INDICATING THAT FFMPEG THREW CRITICAL ERROR AND ERROR BOX SHOULD BE CREATED INSTEAD
REM http://stackoverflow.com/questions/9378972/how-do-i-detect-and-delete-a-file-if-it-is-empty-using-a-dos-batch-file#answer-9379723
>nul findstr "^" "videoinfo.txt" || set /a variable12+=1

REM CREATE A MESSAGE BOX WITH MULTI MEDIA INFO AND TITLE OR AN ERROR BOX
if "!variable12!"=="1" ( echo x=MSGBOX ("Errors detected",48,"Confex MultiMedia File Info - %%~nxi - ERRORS DETECTED"^) > %temp%\TEMPmessage.vbs) else ( echo x=MSGBOX ("!fileContent!",0,"Confex MultiMedia File Info - %%~nxi"^) > %temp%\TEMPmessage.vbs)

call %temp%\TEMPmessage.vbs
del %temp%\TEMPmessage.vbs /f /q

del videoinfo.txt

)


exit

:readFile
REM ORIGINALLY GIVEN BY JEB ON DOSTIPS I MODIFIED SO THAT CHR10 (ENTER KEY IN VBS) CAN BE ECHOED TO THE VIDEOINFO.TXT FILE SO VBS MSGBOX WILL COMPILE CORRECTLY. NOTICE CHR10 HAS ESCAPE CHARACTERS.
setlocal DisableDelayedExpansion
set "text="
for /F "delims=" %%L in ('findstr /n "^" "%~2"') do (
   set "line=%%L"
   setlocal EnableDelayedExpansion
   set "line=!line:\=\S!"
   set "line=!line:*:=!"
   for /F "delims=" %%T in (""!text!!line!^"^& chr^(10^) ^& ^""") do (
     endlocal
     set "text=%%~T"
   )
)
setlocal EnableDelayedExpansion
set "text=!text:"=""!"
set "text=!text:^=^^^^!"
set "text=%text:!=^^^!%" !
set "text=!text:""="!"
for %%L in ("!LF!") DO (
   for /F "delims=" %%T in (""!text!"") do (
     endlocal
     endlocal
     set "%~1=%%~T"
     set "%~1=!%~1:^"^& chr^(10^) ^& ^"=%%~L!"
     set "%~1=!%~1:\S=\!"
   )
)

exit /b



My Usage:

Keep the bat file in the SendTo folder so user can select a video, audio, or other ffmpeg ok'd file and right click and select sendTo and select the bat file.

Where your help is needed - Completing the script with icing by adding ERROR handling.

Code: Select all

ffprobe version N-51683-g9dc88ac Copyright (c) 2007-2013 the FFmpeg developers
  built on Apr  8 2013 21:19:21 with gcc 4.8.0 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libcaca --enable-libfreetype --enable-libgsm --enable-libilbc --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxavs --enable-libxvid --enable-zlib
  libavutil      52. 25.100 / 52. 25.100
  libavcodec     55.  2.100 / 55.  2.100
  libavformat    55.  1.100 / 55.  1.100
  libavdevice    55.  0.100 / 55.  0.100
  libavfilter     3. 49.101 /  3. 49.101
  libswscale      2.  2.100 /  2.  2.100
  libswresample   0. 17.102 /  0. 17.102
  libpostproc    52.  2.100 / 52.  2.100
[mpeg2video @ 020d3c00] Invalid frame dimensions 0x0.
[mp2 @ 020e7da0] Header missing
[mpeg2video @ 020d3c00] Invalid frame dimensions 0x0.
    Last message repeated 5 times
[mpeg @ 021df920] max_analyze_duration 5000000 reached at 5015467 microseconds
Input #0, mpeg, from 'C:\Users\xxx\Desktop\Testing Area\part_005(1).mpg':
  Duration: 00:15:33.14, start: 1.420367, bitrate: 2739 kb/s
    Stream #0:0[0x1e0]: Video: mpeg2video (Main), yuv420p, 720x480 [SAR 8:9 DAR 4:3], 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc
    Stream #0:1[0x1c0]: Audio: mp2, 44100 Hz, stereo, s16p, 128 kb/s


Above is an example of videoinfo.txt file created by ffprobe.exe in my bat file. I would like to remove all the lines up to and including this one:

Code: Select all

libpostproc    52.  2.100 / 52.  2.100
That line doesn't change no matter what file is used by ffmpeg, so it is consistent, and why it's a good reference point. Then remove all the lines after and including this one:

Code: Select all

Input #0, mpeg, from 'C:\Users\xxx\Desktop\Testing Area\part_005(1).mpg':
The

Code: Select all

Input
part of that line is consistent but not the rest of the line. Hopefully that doesn't complicate things too much.

The remaining lines could either be echo'd out to another txt file such as videoerror.txt and then imported back in for processing or these lines can be put into a variable with carriage returns like the way jeb's script works in my bat so the one variable can be echoed out to msgbox vbs script.

So.. to be clear in this example I would only want

Code: Select all

[mpeg2video @ 020d3c00] Invalid frame dimensions 0x0.
[mp2 @ 020e7da0] Header missing
[mpeg2video @ 020d3c00] Invalid frame dimensions 0x0.
    Last message repeated 5 times
[mpeg @ 021df920] max_analyze_duration 5000000 reached at 5015467 microseconds

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Setting a variable from an entire txt file

#15 Post by foxidrive » 29 Nov 2013 20:12

If you put the text in file.txt then this will give you those lines:

Code: Select all

findstr /r /c:"^\[" /c:"^    L" list.txt

Post Reply