Computer Hope
Microsoft => Microsoft DOS => Topic started by: Star-Fire on October 16, 2009, 10:33:15 AM
-
I'm bad English and newbie DOS
I have .bat file:
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:
this is a song!in love ABC
Final.out:
this is a song love
.out file loss 3 character "!in"
Can you fix they help me, plz :P
-
I have .bat file:
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
@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.
-
change the ECHO line to !line! only
How will he get the first 30 characters only of the line?
-
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....
@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
@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.]
@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.
@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%
-
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
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)
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
-
@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. :'(
-
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
for ( loop *.txt ) do (
echo substr(line,0,30)
)
you can use this vbscript
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:
c:\test> cscript /nologo myscript.vbs
best of all, if you can download stuff...try gawk..(see my sig) for parsing files.
C:\test>gawk "{print substr($0,1,30)}" *.txt
-
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.
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.
@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
)
)
-
And you needed to repeat that post even though it was the most recent post?
-
And you needed to repeat that post even though it was the most recent post?
huh?
-
huh?
Still waiting...
-
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.
-
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.
....
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)
-
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.
-
I wonder, gh0std0g74, if you have tested your vbs solution?
-
I wonder, gh0std0g74, if you have tested your (as posted) vbs solution?
for the record...
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
-
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?
-
I wonder, gh0std0g74, if you have tested your vbs solution?
and i wonder why you think i didn't
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?
-
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.
-
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? ???
-
How i can save all line to one file? ???
cscript //nologo scriptname.vbs > file.txt
-
Sorry,
I want say, how i can create output when run this code:
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 >_<
-
1. Save the script with a .vbs extension
2. Run it as I showed you.
-
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.
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?
-
see post #20 again !!!!
-
Thanks your help.
I need use
cscript //nologo scriptname.vbs > file.txt
before run your vbs
I have output file, but I don't want it
print each line on each window
-
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.
-
"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
-
use cscript.exe not wscript.exe to interpret the file.
-
use cscript.exe not wscript.exe to interpret the file.
its so bizarre. i remember i did use cscript.exe, not wscript.exe.
-
Thanks, My computer have wscript.exe and cscript.exe. I used file Bat with
cscript //nologo scriptname.vbs > file.txt
exit /b wscript.exe
scriptname.vbs
and it worked, thanks again :)
-
You ran the script twice.