Computer Hope

Microsoft => Microsoft DOS => Topic started by: Star-Fire on October 16, 2009, 10:33:15 AM

Title: This is Bug in .bat file?
Post by: Star-Fire on October 16, 2009, 10:33:15 AM
 I'm bad English and newbie DOS

 I have .bat file:

Quote
for %%a in ("*.txt") do type %%a >> outfile.out
@echo off
setlocal  enabledelayedexpansion
for /f "tokens=*" %%a in (outfile.out) do (
 set line=%%a
 echo !line:~0,30!>> Final.out
 )

 This file have 2 problem:
 -It will read all file txt but can't read file .txt have space in file name (by DOS?)
 -when echo line, it will loss all character flow exclamation symbol (!)
 Example:
 
  .txt file:
 
Quote
this is a song!in love                     ABC

  Final.out:
 
Quote
this is a song love           

 .out file loss 3 character "!in"

 Can you fix they help me, plz :P
Title: Re: This is Bug in .bat file?
Post by: wbrost on October 16, 2009, 01:49:47 PM
I have .bat file:

Code: [Select]
for %%a in ("*.txt") do type %%a >> outfile.out
@echo off
setlocal  enabledelayedexpansion
for /f "tokens=*" %%a in (outfile.out) do (
 set line=%%a
 echo !line:~0,30!>> Final.out
 )


1)Try changing the .out to .txt
2)set the delims equal to something that is not in the file like the following:
delims==
3)change the ECHO line to !line! only

Code: [Select]
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
for %%a in ("*.txt") do type %%a >> outfile.txt
for /f "delims== tokens=*" %%a in (outfile.txt) do (
 set line=%%a
 echo !line!>> Final.txt
 )

let me know if you have any issues or questions.
Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on October 16, 2009, 05:05:16 PM
Quote
change the ECHO line to !line! only

How will he get the first 30 characters only of the line?
Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on October 17, 2009, 02:25:00 AM
Batch language uses certain special characters for control purposes. E.g. !&<> and others. Text files containing these are difficult to process. Exclamation mark is such a character. Therefore other scripting language is useful. Frequently Visual Basic Script either alone or in hybrid script is a solution. If running Scripting Host is allowed and enabled, this will work.

Enclose filenames (or variables which will expand to a filename) with quotes to include names with spaces.

This script is closest to the original....

Code: [Select]
@echo off
set script="%TEMP%\stringslice.vbs"
echo wscript.echo mid(wscript.arguments(0), (wscript.arguments(1)+1),wscript.arguments(2))>%script%
for %%a in ("*.txt") do type "%%a" >> outfile.out
for /f "tokens=*" %%b in (outfile.out) do (
 for /f "delims==" %%c in ( 'cscript //nologo %script% "%%b" 0 30' ) do echo %%c>>final.out
 )
del %script%

Note that outfile.out and final.out with grow each time you run the script.

In fact the processing of outfile.out can be done in one line but the above is clearer to read I think

Code: [Select]
@echo off
set script="%TEMP%\stringslice.vbs"
echo wscript.echo mid(wscript.arguments(0), (wscript.arguments(1)+1),wscript.arguments(2))>%script%
for %%a in ("*.txt") do type "%%a" >> outfile.out
for /f "tokens=*" %%b in (outfile.out) do for /f "delims==" %%c in ( 'cscript //nologo %script% "%%b" 0 30' ) do echo %%c>>final.out
del %script%

You can eliminate outfile.out altogether by taking the 2nd token of the output of findstr /R "." ("." is regular expression to match all characters). [You could use type *.txt but it produces screen echo of each filename.]

Code: [Select]
@echo off
set script="%TEMP%\stringslice.vbs"
echo wscript.echo mid(wscript.arguments(0), (wscript.arguments(1)+1),wscript.arguments(2))>%script%

for /f "tokens=1,2 delims=:" %%a in ('findstr /R "." *.txt') do (
for /f "delims==" %%c in ( 'cscript //nologo %script% "%%b" 0 30') do (
echo %%c>>final.out
)
)
del %script%

In fact you can do all the processing on one line but it is 153 characters long.

Code: [Select]
@echo off
set script="%TEMP%\stringslice.vbs"
echo wscript.echo mid(wscript.arguments(0), (wscript.arguments(1)+1),wscript.arguments(2))>%script%

for /f "tokens=1,2 delims=:" %%a in ('findstr /R "." *.txt') do for /f "delims==" %%c in ( 'cscript //nologo %script% "%%b" 0 30') do echo %%c>>final.out

del %script%

Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on October 17, 2009, 04:33:13 AM
Code: [Select]
wscript.echo mid(wscript.arguments(0), (wscript.arguments(1)+1),wscript.arguments(2))
alternative:
save the above code as stringslice.vbs either in the same folder as the batch file, or in a folder on your PATH*, and you can use it in any batch file and the batch file posted by the OP becomes a one liner

Code: [Select]
for /f "tokens=1,2 delims=:" %%a in ('findstr /R "." *.txt') do for /f "delims==" %%c in ( 'cscript //nologo %script% "%%b" 0 30') do echo %%c>>final.out
Use it like this

offset and length are numbers (same as batch string slicing)

Code: [Select]
set longstring=This is a long string
for /f "delims==" %%a in ( 'cscript //nologo stringslice.vbs "%longstring%" offset length' ) do set substring=%%a


* or you can supply the full path to the vbs script
Title: Re: This is Bug in .bat file?
Post by: Star-Fire on October 17, 2009, 09:31:14 AM
 @Salmon Trout:
 I tested all your code and it worked but have new problem. Its very slow, I can't use it with many file text have hight size (200,000+ Byte with 3000 line) in short time like old my .bat. :'(

Title: Re: This is Bug in .bat file?
Post by: gh0std0g74 on October 17, 2009, 09:53:23 AM
its very slow because the batch has 3 for loops.... The first loop iterates a text file with 3000 lines and save to an output file. then the second loop does that 3000 times and the next loop as well...furthermore,  with many text files...you do your own maths....

a more efficient approach is to read those text files 1 time only, and get your desired substring from index 0 to 30
ie
Code: [Select]
for ( loop *.txt ) do (
    echo substr(line,0,30)
)

you can use this vbscript
Code: [Select]
Set objFS=CreateObject("Scripting.FileSystemObject")
strFolder = "c:\test"
Set objFolder = objFS.GetFolder(strFolder)
Go (objFolder)
Sub Go(objDIR)
  If objDIR <> "\System Volume Information" Then
    For Each eFolder in objDIR.SubFolders
      Go eFolder
    Next   
  End If
For Each strFile In objDIR.Files
name =strFile.Name
If objFS.GetExtensionName(strFile) = "txt" Then
Set objFile = objFS.OpenTextFile(name)
Do Until objFile.AtEndOfStream
strLine = objFile.ReadLine
WScript.Echo Mid(strLine,1,30)
Loop
    Set objFile = Nothing         
End If
Next
End Sub
save as myscript.vbs and on command line:
Code: [Select]
c:\test> cscript /nologo myscript.vbs

best of all, if you can download stuff...try gawk..(see my sig) for parsing files.
Code: [Select]
C:\test>gawk "{print substr($0,1,30)}" *.txt
Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on October 17, 2009, 10:20:50 AM
its very slow because the batch has 3 for loops.... The first loop iterates a text file with 3000 lines and save to an output file. then the second loop does that 3000 times and the next loop as well...furthermore,  with many text files...you do your own maths....

I don't think all my suggested solutions do that, actually.

Quote from: gh0std0g74
a more efficient approach is to read those text files 1 time only

Didn't you notice my further examples which specifically avoid temp files? I actually mentioned this explicitly.

But I agree batch is slow. Also calling the vbs repeatedly has a big effect.

Code: [Select]
@echo off

set script="%TEMP%\stringslice.vbs"
echo wscript.echo mid(wscript.arguments(0), (wscript.arguments(1)+1),wscript.arguments(2))>%script%

REM For each line output by findstr /R "." *.txt, in the format filename:line
REM put the part after the colon into %%b
REM (This is equivalent to running type on every .txt file in the folder)
REM This is gh0std0g74's "one time only" file read.
for /f "tokens=1,2 delims=:" %%a in ('findstr /R "." *.txt') do (

     REM Put the first 30 characters into %%c
for /f "delims==" %%c in ( 'cscript //nologo %script% "%%b" 0 30') do (

REM Append these as a new line to a file
echo %%c>>final.out

)

)
Title: Re: This is Bug in .bat file?
Post by: Helpmeh on October 17, 2009, 10:23:24 AM

And you needed to repeat that post even though it was the most recent post?
Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on October 17, 2009, 10:25:28 AM
And you needed to repeat that post even though it was the most recent post?

huh?
Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on October 17, 2009, 11:14:42 AM
huh?


Still waiting...
Title: Re: This is Bug in .bat file?
Post by: Geek-9pm on October 17, 2009, 11:43:19 AM
Quote
Quote
this is a song!in love                     ABC

  Final.out:
 
Quote
this is a song love           

 .out file loss 3 character "!in"

That is not a a bug. In standard English we would not put an "!" inside of a word.
That symbol us an escape for the command interpreter.
The output is correct. Nothing is wrong. But it is not what you wanted.
the variable "in" was not defined, so you get nothing. A null string.
Title: Re: This is Bug in .bat file?
Post by: gh0std0g74 on October 17, 2009, 05:42:40 PM
I don't think all my suggested solutions do that, actually.
...
Didn't you notice my further examples which specifically avoid temp files? I actually mentioned this explicitly.
OP mentioned he has used all your solution and its slow and he has big files. therefore my hypothesis is that he had used the one that has used the version with the most number of redundant loops...and you can be sure i read your post.


Quote
Code: [Select]
....
for /f "tokens=1,2 delims=:" %%a in ('findstr /R "." *.txt') do (
     REM Put the first 30 characters into %%c
for /f "delims==" %%c in ( 'cscript //nologo %script% "%%b" 0 30') do (
....
though its an improved version, there's still no reason to invoke cscript 3000 * n  times for each lines of each text file. its better to do them in one invocation of cscript process (since considering they are big files)
Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on October 18, 2009, 02:27:49 AM
Quote
there's still no reason to invoke cscript 3000 * n  times for each lines of each text file

Cscript is invoked ***once*** for each line of each text file.
Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on October 18, 2009, 02:56:41 AM
I wonder, gh0std0g74, if you have tested your vbs solution?

Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on October 18, 2009, 03:23:08 AM
I wonder, gh0std0g74, if you have tested your (as posted) vbs solution?

for the record...

Code: [Select]
Set objFS=CreateObject("Scripting.FileSystemObject")
strFolder = "c:\test"
Set objFolder = objFS.GetFolder(strFolder)
Go (objFolder)
Sub Go(objDIR)
  If objDIR <> "\System Volume Information" Then
    For Each eFolder in objDIR.SubFolders
      Go eFolder
    Next   
  End If
For Each strFile In objDIR.Files
name =strFile.Name
If objFS.GetExtensionName(strFile) = "txt" Then
Set objFile = objFS.OpenTextFile(name)
Do Until objFile.AtEndOfStream
strLine = objFile.ReadLine
WScript.Echo Mid(strLine,1,30)
Loop
    Set objFile = Nothing         
End If
Next
End Sub


Title: Re: This is Bug in .bat file?
Post by: gh0std0g74 on October 18, 2009, 05:06:05 AM
Cscript is invoked ***once*** for each line of each text file.
yes...that's my point.. thanks for clarifying my bad english. If each text file has 3000 lines and there are 10 such files for example,  then cscript is invoked 3000*10 times.... am i correct to say that?
Title: Re: This is Bug in .bat file?
Post by: gh0std0g74 on October 18, 2009, 05:10:51 AM
I wonder, gh0std0g74, if you have tested your vbs solution?
and i wonder why you think i didn't
Code: [Select]
C:\test>more test.vbs
Set objFS=CreateObject("Scripting.FileSystemObject")
strFolder = "c:\test"
Set objFolder = objFS.GetFolder(strFolder)
Go (objFolder)
Sub Go(objDIR)
  If objDIR <> "\System Volume Information" Then
    For Each eFolder in objDIR.SubFolders
        Go eFolder
    Next
  End If
        For Each strFile In objDIR.Files
                name =strFile.Name
                If objFS.GetExtensionName(strFile) = "txt" Then
                        Set objFile = objFS.OpenTextFile(name)
                        Do Until objFile.AtEndOfStream
                                strLine = objFile.ReadLine
                                WScript.Echo Mid(strLine,1,10)
                        Loop
                    Set objFile = Nothing
                End If
        Next
End Sub
C:\test>more file.txt
file.txt line one
file.txt line two

C:\test>more file1.txt
file1.txt line one
file1.txt line two

C:\test>more file2.txt
file2.txt line one
file2.txt line two

C:\test>cscript /nologo test.vbs
file.txt l
file.txt l
file1.txt
file1.txt
file2.txt
file2.txt

so what's your nitpick all about?
Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on October 18, 2009, 05:23:53 AM
and i wonder why you think i didn't

My mistake; I assumed that since you hard coded the folder name, I could run it from anywhere, but in fact it only works when run from inside the folder.
Title: Re: This is Bug in .bat file?
Post by: Star-Fire on October 22, 2009, 09:39:37 AM
Quote
Set objFS=CreateObject("Scripting.FileSystemObject")
strFolder = "c:\test"
Set objFolder = objFS.GetFolder(strFolder)
Go (objFolder)
Sub Go(objDIR)
  If objDIR <> "\System Volume Information" Then
    For Each eFolder in objDIR.SubFolders
        Go eFolder
    Next
  End If
        For Each strFile In objDIR.Files
                name =strFile.Name
                If objFS.GetExtensionName(strFile) = "txt" Then
                        Set objFile = objFS.OpenTextFile(name)
                        Do Until objFile.AtEndOfStream
                                strLine = objFile.ReadLine
                                WScript.Echo Mid(strLine,1,10)
                        Loop
                    Set objFile = Nothing
                End If
        Next
End Sub
How i can save all line to one file?  ???
Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on October 22, 2009, 11:59:04 AM
How i can save all line to one file?  ???

Code: [Select]
cscript //nologo scriptname.vbs > file.txt
Title: Re: This is Bug in .bat file?
Post by: Star-Fire on October 27, 2009, 02:37:42 AM
Sorry,
 I want say, how i can create output when run this code:
Quote
Set objFS=CreateObject("Scripting.FileSystemObject")
strFolder = "c:\test"
Set objFolder = objFS.GetFolder(strFolder)
Go (objFolder)
Sub Go(objDIR)
  If objDIR <> "\System Volume Information" Then
    For Each eFolder in objDIR.SubFolders
        Go eFolder
    Next
  End If
        For Each strFile In objDIR.Files
                name =strFile.Name
                If objFS.GetExtensionName(strFile) = "txt" Then
                        Set objFile = objFS.OpenTextFile(name)
                        Do Until objFile.AtEndOfStream
                                strLine = objFile.ReadLine
                                WScript.Echo Mid(strLine,1,10)
                        Loop
                    Set objFile = Nothing
                End If
        Next
End Sub
I don't know vbs >_<
Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on October 27, 2009, 02:46:20 AM
1. Save the script with a .vbs extension
2. Run it as I showed you.
Title: Re: This is Bug in .bat file?
Post by: Star-Fire on November 01, 2009, 11:26:37 PM
I have save all your code in file vbs and run it. Program run and print each line on each window and don't create output file.

Quote
Set objFS=CreateObject("Scripting.FileSystemObject")
strFolder = "G:\AH\aa"
Set objFolder = objFS.GetFolder(strFolder)
Go (objFolder)
Sub Go(objDIR)
  If objDIR <> "\System Volume Information" Then
    For Each eFolder in objDIR.SubFolders
        Go eFolder
    Next
  End If
        For Each strFile In objDIR.Files
                name =strFile.Name
                If objFS.GetExtensionName(strFile) = "txt" Then
                        Set objFile = objFS.OpenTextFile(name)
                        Do Until objFile.AtEndOfStream
                                strLine = objFile.ReadLine
                                WScript.Echo Mid(strLine,1,10)
                        Loop
                    Set objFile = Nothing
                End If
        Next
End Sub
"G:\AH\aa" it my path and folder "aa" have many file txt.

 My "Scripting Host" error?
Title: Re: This is Bug in .bat file?
Post by: gh0std0g74 on November 01, 2009, 11:33:59 PM
see post #20 again !!!!
Title: Re: This is Bug in .bat file?
Post by: Star-Fire on November 01, 2009, 11:52:54 PM
Thanks your help.
 I need use
Quote
cscript //nologo scriptname.vbs > file.txt

before run your vbs

 I have output file, but I don't want it

Quote
print each line on each window
Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on November 02, 2009, 12:44:26 AM
Quote
cscript //nologo scriptname.vbs > file.txt

Don't type "scriptname.vbs", type the actual name that you saved the script as. After it has finished, load file.txt into an editor such as Notepad so you can see it.
Title: Re: This is Bug in .bat file?
Post by: Star-Fire on November 03, 2009, 12:32:01 AM
Quote
"scriptname.vbs"
I know it is name my script, "WScript.Echo" will print all line when I run script. One window "Window Script host" will open with each line, I need choose "enter" per each (I can't do it with 3000+ line). I want stop it when i have output File
Title: Re: This is Bug in .bat file?
Post by: BC_Programmer on November 03, 2009, 04:02:30 AM
use cscript.exe not wscript.exe to interpret the file.
Title: Re: This is Bug in .bat file?
Post by: gh0std0g74 on November 03, 2009, 04:21:41 AM
use cscript.exe not wscript.exe to interpret the file.
its so bizarre. i remember i did use cscript.exe, not wscript.exe.
Title: Re: This is Bug in .bat file?
Post by: Star-Fire on November 04, 2009, 06:56:46 AM
Thanks, My computer have wscript.exe and cscript.exe. I used file Bat with
Quote
cscript //nologo scriptname.vbs > file.txt
exit /b wscript.exe
scriptname.vbs

and it worked, thanks again :)
Title: Re: This is Bug in .bat file?
Post by: Salmon Trout on November 04, 2009, 07:58:50 AM
You ran the script twice.