I need to do multiple find and replace operation on a single file. The setup is as follows:
Text data - File.txt
Replacement data - File2.txt
The structure of File2.txt is like this:
ABC,XYZ
MNB,OPI
GHI,TRY
The first column is my original name (eg. ABC) and replaced with the 2nd name (eg. XYZ). This has to be done in the original File.txt
I can write a code to do a single change or to increment the name from ABC to ABC_Date but I am confused about how to loop and read both to and from names.
Any help is appreciated.
I was able to solve this by gluing together answers from:
How can you find and replace text in a file using the Windows command-line environment?
How do you loop through each line in a text file using a windows batch file?
The code is:
for /F "tokens=1,2,3" %%i in (myfile.txt) do call :process %%i %%j %%k
goto thenextstep
:process
#echo %1
#echo %2
cscript replace.vbs "C:\newfile.txt" "%1" "%2"
goto :EOF
replace.vbs
Const ForReading = 1
Const ForWriting = 2
strFileName = Wscript.Arguments(0)
strOldText = Wscript.Arguments(1)
strNewText = Wscript.Arguments(2)
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(strFileName, ForReading)
strText = objFile.ReadAll
objFile.Close
strNewText = Replace(strText, strOldText, strNewText)
Set objFile = objFSO.OpenTextFile(strFileName, ForWriting)
objFile.Write strNewText 'WriteLine adds extra CR/LF
objFile.Close
Here, This is the sample powershell code to replace multiple words from another file. You have to change the $file1Text value and $file2Text value
$file1Text = "this is sample text. You have to get the text from file" ; # your file1 data
$file2Text = "this,here it","text,data","file,physical file" # your file2 lines
$finalText = $file1Text ; # Temp variable [ optional ] : you can use file1Text directly
foreach ($str in $file2Text)
{
$split = $str.Split(',')
$find = $split[0]
$replace = $split[1]
$finalText = $finalText.Replace($find,$replace)
}
cls
"Original Text : " + $file1Text
"Replaced Text : " + $finalText
Related
I have a text file with a youtube link,
text file = url.txt , which consist,
https://www.youtube.com/watch?v=Videocode
my need is, by running a batch file how to get only that Videocode as output in another text file.
For example, if am running url.bat which need to convert "https://www.youtube.com/watch?v=Videocode" into "Videocode"
I hope you understand my need. Please gave me some solutions. Thanks in advance.
Taking the question as asked literally, a text file named url.txt containing a link in the format https://www.youtube.com/watch?v=Videocode, url.bat could just contain this:
#For /F "UseBackQ Tokens=2 Delims==&" %%A In ("C:\Users\niranja\Desktop\url.txt") Do #(Echo %%A)>"output.txt"
Change the path to your url.txt, C:\Users\niranja\Desktop\, to suit; or if it is in the same location as url.bat remove that path completely. The video ID you were looking for should be written to a file named output.txt in the same directory as url.bat.
Note: If question as written does not match your real intent, take a look at the link provided by Hackoo and start putting something together yourself!
Here is an idea with a vbscript using a Regex to extract the "Videocode"
Data = "https://www.youtube.com/watch?v=Videocode" & vbCrlf &_
"http://www.youtube.com/watch?v=iwGFalTRHDA" & vbCrlf &_
"http://www.youtube.com/watch?v=iwGFalTRHDA&feature=related" & vbCrlf &_
"http://youtu.be/iwGFalTRHDA" & vbCrlf &_
"http://youtu.be/n17B_uFF4cA" & vbCrlf &_
"http://www.youtube.com/embed/watch?feature=player_embedded&v=r5nB9u4jjy4" & vbCrlf &_
"http://www.youtube.com/watch?v=t-ZRX8984sc" & vbCrlf &_
"http://youtu.be/t-ZRX8984sc"
Data_Extracted = Extract(Data,"http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)(&(amp;)?[\w\?=]*)?")
WScript.echo Data_Extracted
'************************************************
Function Extract(Data,Pattern)
Dim oRE,oMatches,Match,Line
set oRE = New RegExp
oRE.IgnoreCase = True
oRE.Global = True
oRE.Pattern = Pattern
set oMatches = oRE.Execute(Data)
If not isEmpty(oMatches) then
For Each Match in oMatches
Line = Line & Match.SubMatches(0) & vbcrlf
Next
Extract = Line
End if
End Function
'************************************************
EDIT : Using an hybrid code batch with a vbscript
#echo off
Title Extract Videocode from Youtube links
Set "Tmpvbs=%temp%\Tmpvbs.vbs"
Set "InputFile=URL.txt"
Set "OutPutFile=OutPutCode.txt"
Call :Extract "%InputFile%" "%OutPutFile%"
Start "" "%OutPutFile%" & exit
::****************************************************
:Extract <InputData> <OutPutData>
(
echo Data = WScript.StdIn.ReadAll
echo Data = Extract(Data,"http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/^)([\w\-\_]*)(&(amp;)?[\w\?=]*)?"^)
echo WScript.StdOut.WriteLine Data
echo '************************************************
echo Function Extract(Data,Pattern^)
echo Dim oRE,oMatches,Match,Line
echo set oRE = New RegExp
echo oRE.IgnoreCase = True
echo oRE.Global = True
echo oRE.Pattern = Pattern
echo set oMatches = oRE.Execute(Data^)
echo If not isEmpty(oMatches^) then
echo For Each Match in oMatches
echo Line = Line ^& Match.SubMatches(0^) ^& vbcrlf
echo Next
echo Extract = Line
echo End if
echo End Function
echo '************************************************
)>"%Tmpvbs%"
cscript /nologo "%Tmpvbs%" < "%~1" > "%~2"
If Exist "%Tmpvbs%" Del "%Tmpvbs%"
exit /b
::**********************************************************************************
this is my problem:
on a Windows 2003 server I've a folder (c:\test), and every day an application put 3 new files on it.
1° file:
31201610181207000100000000630001
31201610181213000100000000440001
31201610181227000100000000630001
....
2° file:
31201610181214000100000000380002
31201610181234000100000009830002
31201610181344000100000000380002
...
3° file:
31201610181826000100000000580003
31201610190722000100000000580003
31201610191801000100000000580003
...
My goal is to replace ONLY the last 4 characters on each file with a .bat or .vbs script (0001 --> 0031) (0002 --> 0032) (0003 --> 0033).
I've done a .vbs file who works, but it search on all string and not on the last 4 characters.
Option Explicit
Dim objFSO, strFolder, objFolder, objFile
Dim strOldValue1, strNewValue1, strNewValue2, strOldValue2, strNewValue3,
strOldValue3, objRead, strContents, objWrite
Const ForReading = 1
Const ForWriting = 2
strFolder = "c:\test"
strOldValue1 = "0001"
strNewValue1 = "0031"
strOldValue2 = "0002"
strNewValue2 = "0032"
strOldValue3 = "0003"
strNewValue3 = "0033"
' I take the folder
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(strFolder)
' I count the file on the folder
For Each objFile In objFolder.Files
' Read file with textstream object.
Set objRead = objFSO.OpenTextFile(objFile.Path, ForReading)
' Trap error if file is empty or cannot read.
On Error Resume Next
strContents = objRead.readall
If (Err.Number <> 0) Then
On Error GoTo 0
Wscript.Echo "Cannot read: " & objFile.Path
strContents = ""
End If
On Error GoTo 0
objRead.Close
' check what's is inside the folder
If (InStr(strContents, strOldValue1) > 0) Then
strContents = Replace(strContents, strOldValue1, strNewValue1)
Set objWrite = objFSO.OpenTextFile(objFile.Path, ForWriting)
objWrite.Write strContents
objWrite.Close
End If
If (InStr(strContents, strOldValue2) > 0) Then
strContents = Replace(strContents, strOldValue2, strNewValue2)
Set objWrite = objFSO.OpenTextFile(objFile.Path, ForWriting)
objWrite.Write strContents
objWrite.Close
End If
If (InStr(strContents, strOldValue3) > 0) Then
strContents = Replace(strContents, strOldValue3, strNewValue3)
Set objWrite = objFSO.OpenTextFile(objFile.Path, ForWriting)
objWrite.Write strContents
objWrite.Close
End If
next
Thanks for any help!!
Here is a short batch script, which immediately modifies all files C:\test\*.* accordingly:
for %%F in ("C:\test\*.*") do (
for /F "delims=" %%L in ('type "%%~F" ^& ^> "%%~F" rem/') do (
set "LINE=%%L"
setlocal EnableDelayedExpansion
set "LEFT=!LINE:~,-4!"
set "RIGHT=!LINE:~-4!"
if "!RIGHT!"=="0001" set "RIGHT=0031"
if "!RIGHT!"=="0002" set "RIGHT=0032"
if "!RIGHT!"=="0003" set "RIGHT=0033"
>> "%%~F" echo(!LEFT!!RIGHT!
endlocal
)
)
Using JREPL.BAT - a regular expression find/replace utility
for %%F in (c:\test\*) do call jrepl "000(?=[123]$)" "003" /f "%%F" /o -
The above looks at the end of each line for "000" before a "1", "2", or "3", and substitutes "003" for the "000".
JREPL is pure script (hybrid batch/JScript) that runs natively on any Windows machine from XP onward - No 3rd party exe file required.
Thank you very much!!!! it works!!
Also, if you're interested I've found how the make my script work:
I've to add the & VBCrlf to the variable, in this way the script will search for the value + the new line.
strOldValue1 = "0001" & VBCrlf
strNewValue1 = "0031" & VBCrlf
strOldValue2 = "0002" & VBCrlf
strNewValue2 = "0032" & VBCrlf
strOldValue3 = "0003" & VBCrlf
strNewValue3 = "0033" & VBCrlf
I have a list of folder paths that I want to loop through and get the files and creation date and then send a email notification that these files have been uploaded to the ftp. I have got everything working but I am having trouble looping through the folders to get the files. I think it loops through the text file but by the time i get to my second loop I think it is only looping through the last path that was in the text doc as the variable was getting overwritten. I tried enclosing the second for statement with parentheses for the first for statement but did not work. Here is my code:
scanFTPCLients.bat
#echo off
setlocal EnableDelayedExpansion
cls
#pushd %~dp0
set i=0
for /F "tokens=*" %%i in (Pathlist.txt) do (
set fp=%%i
set LIST=
for /r "%fp%" %%a in (*.*) do set i=i+1
set LIST=!LIST! ---%deptClient%--- %%~na ----UPLOAD TIME---- %%~ta
)
set LIST=%LIST:~1%
IF %i% NEQ 0 (wscript "%~dp0FTPFilesUploadedNotification.vbs")
popd
Pathlist.txt
\\vavm\CINICO\Incoming
\\vavm\CIS\Incoming
\\vavm\Forcht\Incoming
\\vavm\HPC\Incoming
\\vavm\K\Incoming
\\vavm\MWEmpCC\Incoming
\\vavm\National Labor Benefits\Incoming
\\vavm\PeriSons\Incoming
\\vavm\US\Incoming
\\vavm\K\Incoming
FTPFilesNotification.vbs
dim outputArray
dim inputText
dim message
inputText = CreateObject("WScript.Shell").ExpandEnvironmentStrings("%LIST%")
outputArray = split(inputText, " ")
for each x in outputArray
message = message & x & vbCRLF
next
Set MyEmail=CreateObject("CDO.Message")
MyEmail.Subject="Clients Imported to System"
MyEmail.From="SYSTEMFUNCTION#mrsllc.org"
MyEmail.To="rickg#gmail.com"
MyEmail.TextBody= "The Following Clients have been imported to the system: " & vbCRLF & message
MyEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing")=2
MyEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver")="mail.org"
MyEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport")=25
MyEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate")=1
MyEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusername")="username"
MyEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendpassword")="password"
MyEmail.Configuration.Fields.Update
MyEmail.Send
set MyEmail=nothing
For comparison, in PowerShell, it could be:
$emailSettings = #{
From = "you#example.org"
To = "you#example.org"
Subject = "Upload report"
SmtpServer = "yourmailserver"
}
$report = dir -Path #(gc pathlist.txt) | select FullName, CreationTime
Send-MailMessage #emailSettings -Body "$($report|ConvertTo-Html)" -BodyAsHtml
This shows how to loop through files in vbscript
'On Error Resume Next
Set fso = CreateObject("Scripting.FileSystemObject")
Dirname = InputBox("Enter Dir name")
'Searchterm = Inputbox("Enter search term")
ProcessFolder DirName
Sub ProcessFolder(FolderPath)
On Error Resume Next
Set fldr = fso.GetFolder(FolderPath)
Set Fls = fldr.files
For Each thing in Fls
' Set contents = thing.OpenAsTextStream
' If err.number = 0 then
' If Instr(contents.readall, searchterm) > 1 then msgbox thing.path
' Else
' err.clear
' End If
msgbox Thing.Name & " " & Thing.DateLastModified
Next
Set fldrs = fldr.subfolders
For Each thing in fldrs
ProcessFolder thing.path
Next
End Sub
To send mail
Set emailObj = CreateObject("CDO.Message")
emailObj.From = "dc#gail.com"
emailObj.To = "dc#gail.com"
emailObj.Subject = "Test CDO"
emailObj.TextBody = "Test CDO"
Set emailConfig = emailObj.Configuration
msgbox emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver")
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.gmail.com"
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 465
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = true
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/sendusername") = "YourUserName"
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "Password1"
emailConfig.Fields.Update
emailObj.Send
If err.number = 0 then Msgbox "Done"
To read a file line by line
On Error Resume Next
Set Fso = CreateObject("Scripting.FileSystemObject")
Set File = Fso.CreateTextFile("C:\myfile.txt", True)
If err.number <> 0 then
Wscript.Echo "Error: " & err.number & " " & err.description & " from " & err.source
err.clear
wscript.exit
End If
Do Until File.AtEndOfStream
Msgbox File.readline
Loop
Changed. Not sure what you want to do about sending lines (one at a time or send all when done). If one at a time, integrate into this. If all at once at end, then send output to a temp file and send it.
#echo off
pushd %~dp0
set /A Cnt=0
for /F "tokens=*" %%i in (Pathlist.txt) do (
echo i= %%i
for /f "usebackq tokens=*" %%a in (`Dir /s /b %%i\*.*`) do (
echo %%~na - %%~ta
set /A Cnt+=1
)
)
echo(Cnt=%Cnt%
pause
popd
I have a batch file which is used by dragging a folder containing .mp3s into the batch.
#echo off
cd %~dp0
setlocal enabledelayedexpansion enableextensions
set FLDR="%1"
if not defined FLDR ( echo Drag a folder to the batch to play its contents.
pause
goto:EOF )
for %%x in (%FLDR%\*.mp3) do set "MP3=!MP3! "%%x""
mp3player %MP3%
pause
It works fine with actual folders, but when dragging shortcuts, the variable %FLDR% ends up as "c:\link location\folder.lnk" instead of the actual folder location.
I have no idea how to get around this.
Here is a way to get the target using a little hybrid VBS/Batch file function.
#echo off
setlocal
Call :GetTarget "%~1" tgt
echo %tgt%
pause
exit /b
:GetTarget
#echo off & setlocal
set gt=%temp%\_.vbs
echo set WshShell = WScript.CreateObject("WScript.Shell")>%gt%
echo set Lnk = WshShell.CreateShortcut(WScript.Arguments.Unnamed(0))>>%gt%
echo wscript.Echo Lnk.TargetPath>>%gt%
set script=cscript //nologo %gt%
For /f "delims=" %%a in ( '%script% "%~1"' ) do set target=%%a
del %gt%
endlocal & set %~2=%target%
exit /b
HYBRID SCRIPT! No silly little temporary files.
::'<SUB>#echo off
::'<SUB>set shortcut=%~1
::'<SUB>if not defined shortcut goto 'usage
::'<SUB>if not %shortcut:~-4%==.lnk (if not %shortcut:~-4%==.url (set errorlevel=1
::'<SUB>goto 'usage ))
::'<SUB>if not exist %shortcut% (echo Error: Nonexistent shortcut
::'<SUB>set errorlevel=1
::'<SUB>goto:EOF )
::'<SUB>setlocal
::'<SUB>for /f "delims=" %%T in ('cscript //nologo //e:vbs %~nx0 "%shortcut%"') do set thing=%%T
::'<SUB>endlocal & set shortcut=%thing%
::'<SUB>goto:EOF
:'usage
::'<SUB>echo command-line shortcut redirect utility
::'<SUB>echo Usage: shortcut [file.lnk ^| file.url]
::'<SUB>echo The resulting link will be output to the %%shortcut%% variable.
::'<SUB>goto:EOF
set WshShell = WScript.CreateObject("WScript.Shell")
set Lnk = WshShell.CreateShortcut(WScript.Arguments.Unnamed(0))
wscript.Echo Lnk.TargetPath
Where <SUB> indicates the substitute character.
UPDATE: I found a much fully vbscript solution over at Wayne's World of IT, and modified it slightly to suit my needs:
If WScript.Arguments.UnNamed.Count = 1 Then
strShortcut = WScript.Arguments.UnNamed(0)
Else
WScript.Echo "Please supply the name of an lnk file or directory to read, eg c:\test.lnk or c:\shortcuts"
WScript.Quit(1)
End If
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FolderExists(strShortCut) Then
Set objFolder = objFSO.getFolder(strShortcut)
For Each objfile in objFolder.Files
If objfile.type = "Shortcut" Then
Call Readshortcut(objFile.Path, strProperties)
dtmCreationDate = objFile.DateCreated
WScript.Echo dtmCreationDate & "," & strProperties
End If
Next
ElseIf objFSO.FileExists(strShortCut) Then
Call Readshortcut(strShortcut, strProperties)
WScript.Echo strProperties
Else
WScript.Echo "Error: Could not read '" & strShortcut & "'"
WScript.Quit(2)
End If
Set objFSO = Nothing
Function Readshortcut(ByRef strShortcut, ByRef strProperties)
set objWshShell = WScript.CreateObject("WScript.Shell")
set objShellLink = objWshShell.CreateShortcut(strShortcut)
strProperties = objShellLink.TargetPath & " " & objShellLink.Arguments
Set objShellLink = Nothing
Set objWshshell = Nothing
End Function
I've two files
file 1:
PROCESS_NAME
wf_1
wf_2
wf_3
file 2:
wf_1 - [Running]
wf_2 - [Succeeded]
wf_2 - [Succeeded]
So now I need to compare the above two files and have to remove the names in file1 for which the status in file2 is [Succeeded]. Struggling for hte past 3 days.
Result should be
file 1:
wf_1
Appreciate any help.
Here you go
#echo off
setlocal enabledelayedexpansion
for /f "tokens=*" %%a in (file1.txt) do (
for /f "skip=1 tokens=*" %%b in ('find "[Succeeded]" file2.txt') do (
set check=%%b
set check=!check: - [Succeeded]=!
if "%%a"=="!check!" set bool=true
)
if not "!bool!"=="true" echo %%a >>new.txt
)
del file1.txt /f /q
ren new.txt file1.txt
Just replace file1.txt and file2.txt with your actual file names.
Const ForReading = 1
Const TextCompare = 1
Dim File1, File2, OutputFile
File1 = "D:\1t\test1\ddir11.txt"
File2 = "D:\1t\test1\ddir12.txt"
OutputFile = "D:\1t\test1\outfile.txt"
Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
If ObjFSO.FileExists(File1) Then
Dim objFile1 : Set objFile1 = objFSO.OpenTextFile(File1, ForReading)
Else
WScript.Quit
End If
' Dictionary object for reference file.
Dim RefDict : Set RefDict = CreateObject("Scripting.Dictionary")
RefDict.CompareMode = TextCompare
Dim StrLine, SearchLine, strNotFound
' Read reference file into dictionary object.
Do Until objFile1.AtEndOfStream
StrLine = Trim(objFile1.ReadLine)
'MsgBox (StrLine)
if Not RefDict.Exists(StrLine) Then
RefDict.Add StrLine, "1"
End If
Loop
Dim a,s,i
a = RefDict.Keys
'read dictionary....
'For i = 0 To RefDict.Count -1 ' Iterate the array.
' s = s & a(i) & "<BR>" ' Create return string.
'Next
objFile1.Close
' File that may have more or less lines.
If ObjFSO.FileExists(File2) Then
Dim objFile2 : Set objFile2 = objFSO.OpenTextFile(File2, ForReading)
Else
WScript.Quit
End If
' Search 2nd file with reference file.
Do Until objFile2.AtEndOfStream
SearchLine = Trim(objFile2.ReadLine)
If Not RefDict.Exists(SearchLine) Then
If IsEmpty(strNotFound) Then
strNotFound = SearchLine
Else
strNotFound = strNotFound & vbCrlf & SearchLine
End If
End If
Loop
objFile2.Close
If IsEmpty(strNotFound) or strNotFound = "" Then
End If
Dim objFile3 : Set objFile3 = objFSO.CreateTextFile(OutputFile, True)
MsgBox ("str:" & strNotFound)
objFile3.WriteLine strNotFound
objFile3.Close