In File_1 I have:
Word_1;ger
Word_1;gr
Word_1;greber
Word_1;gaerfsd
Word_2;gerbhge
Word_2;tgbzrfvd
Word_3;gzfdfdc
I want to calculate the number of duplicates of each first column of each line then, depending on the number of duplicates(one or different than one), I will copy paste them to two different files.
File_2 will contain:
Word_3;gzfdfdc
File_3 will contain:
Word_1;ger
Word_1;gr
Word_1;greber
Word_1;gaerfsd
Word_2;gerbhge
Word_2;tgbzrfvd
Here is the code that I wrote:
setlocal EnableDelayedExpansion
(for /f "tokens=1-2 delims=;" %%a in (File_1) do (
set current_line=%%a
if "!current_line!" NEQ "!previous_line!" (
for /f %%C in ('Find /C %%a ^< File_1) do (
set Count=%%C
if "!Count!==1" (
findstr %%a File_1 >>File_2
)
if not "!Count!==1" (
findstr %%a File_1 >>File_3
)
)
)
set previous_line=!current_line!
)
It doesn't seem to work. Any Help ?
removed an unneeded variable, corrected an erroneous if syntax and added some quotes for "best practice". Seems to do exactly, what you intend:
setlocal EnableDelayedExpansion
(for /f "tokens=1-2 delims=;" %%a in (File_1.txt) do (
if "%%a" NEQ "!previous_line!" (
for /f %%C in ('Find /C "%%a" ^< File_1.txt') do (
if "%%C"=="1" (
findstr "%%a" File_1.txt >>File_2.txt
) else (
findstr "%%a" File_1.txt >>File_3.txt
)
)
)
set "previous_line=%%a"
))
Although your (corrected) code works ok, it is pretty inefficient. You execute findstr command two times for each group of duplicates. If the input file is large, this method could take a lot of time.
You may get the same result with a single for /F pass over the file, with no use of findstr:
#echo off
setlocal EnableDelayedExpansion
del File_2.txt File_3.txt 2>NUL
set "last1="
set "moreThanOne="
for /f "tokens=1-2 delims=;" %%a in (File_1.txt) do (
if "%%a" equ "!last1!" (
>> file_3.txt echo !last1!;!last2!
set "moreThanOne=1"
) else (
if defined moreThanOne (
>> file_3.txt echo !last1!;!last2!
) else if defined last1 (
>> file_2.txt echo !last1!;!last2!
)
set "moreThanOne="
)
set "last1=%%a"
set "last2=%%b"
)
if defined moreThanOne (
>> file_3.txt echo !last1!;!last2!
) else (
>> file_2.txt echo !last1!;!last2!
)
Related
My batch file is silently ending execution on the first loop (for /d "delims= eol=|" %%d in (*.*) do () and I can't tell why.
I'm not calling any other batch files
My subfolder names DO contain spaces, which I tried to handle with "delims= eol=|"
I never see !parent!!folder! echoed and it doesn't pause at the end. What am I doing wrong?
#Echo off
setlocal enabledelayedexpansion
pushd "%~dp0"
set "parent=%~dp0"
echo !parent!
set "destination=\\(test destination folder)\"
rem SET "destination=\\(prod destination folder)\"
set "FileCount=0"
for /d "delims= eol=|" %%d in (*.*) do (
set "folder=%%d"
echo !parent!!folder!
pause
for %%f in ("!parent!!folder!\(file identifying-pattern)*.DAT") do (
echo "File Type 1"
pause
if !FileCount! lss 200 (
set /a !FileCount!+=1
ECHO !FileCount!
ECHO !parent!!folder!%%f
ECHO !destination!%%f
MOVE "%%f" "!destination!"
)
(
for %%f in ("!parent!!folder!\(file identifying-pattern)*.DAT") do (
echo "File Type 2"
pause
if !FileCount! lss 200 (
set /a !FileCount!+=1
ECHO !FileCount!
ECHO !parent!!folder!%%f
ECHO !destination!%%f
MOVE "%%f" "!destination!"
)
)
)
for /d %%d in (*.*) do (
set "folder=%%d"
if not %%d==Archive (
if not %%d==Hold (
dir /b "!folder!"|find /v "">nul && ECHO "!folder! NOT EMPTY"||rmdir "!parent!!folder!"
)
)
)
pause
popd
I've took a guess at what you were doing, trying not to change the structure too much!
You'll need to add your destinations on lines 4 and 5 and your file patterns to lines 8 and 9 as necessary. (Please make sure you do not end your destination paths with back slashes):
#Echo Off
CD /D "%~dp0" 2>Nul || Exit /B
Set "Destination=\\(test destination folder)"
Rem Set "Destination=\\(prod destination folder)"
If Not Exist "%destination%\" Exit /B
Set "Pattern1=(file identifying-pattern)"
Set "Pattern2=(file identifying-pattern)"
Set /A Type1Count=Type2Count=0
SetLocal EnableDelayedExpansion
For /D %%A In (*) Do (
For %%B In ("%%A\%Pattern1%*.dat") Do (
Echo "File Type 1"
Set /A Type1Count +=1
If !Type1Count! Lss 200 (
Echo !Type1Count!. "%CD%\%%A\%%B" --^> "%Destination%\%%B"
If Not Exist "%Destination%\%%B\" MD "%Destination%\%%B"
Move /Y "%%B" "%Destination%\%%B">Nul
)
)
For %%C In ("%%A\%Pattern2%*.dat") Do (
Echo "File Type 2"
Set /A Type2Count +=1
If !Type2Count! Lss 200 (
Echo !Type2Count!. "%CD%\%%B\%%C" --^> "%Destination%\%%C"
If Not Exist "%Destination%\%%C\" MD "%Destination%\%%C"
Move /Y "%%C" "%Destination%\%%C">Nul
)
)
If /I Not "%%A"=="Archive" (
If /I Not "%%A"=="Hold" (
Set "file="
For %%D In (*) Do Set "file=1"
If Defined file (Echo %%A NOT EMPTY) Else RD "%%A" 2>Nul
)
)
)
Pause
If you're happy with it in your test you can Remark line 4 and unRemark line 5.
I have a program to search drives for a specific file. The only problem is is that i wont know what drive it is on. The problem occurs when it searches a drive for a file that isn't there is there a way to go on to the next drive after say like 10 seconds. Heres my code so far
#echo off
setlocal EnableDelayedExpansion
set count=1
for /f "skip=1" %%a in ('wmic logicaldisk get caption') do (
set drive!count!=%%a
set /a count+=1
)
set "gh=!drive1!"
::Change this to do whatever with the variables
set "fh=!drive2!"
set "hh=!drive3!"
set "jh=!drive4!"
For /R %gh%\ %%G IN (*.ut2) do set jk="%%~dpG"
if defined jk (
echo %jk%
) else (
goto next
)
for /r %jk% %%a in (*) do if "%%~nxa"=="CTF-Hydro-16-2k3.ut2" set k=%%~dpnxa
if defined k (
echo %k% found
pause
cls
echo You have it
goto end
) else (
echo Map not found
copy %CD:~0,3%\Unrealmap\CTF-Hydro-16-2k3.ut2 %jk%
goto end
)
:next
For /R %fh%\ %%G IN (*.ut2) do set ht="%%~dpG"
if defined ht (
echo %ht%
) else (
goto there
)
for /r %ht% %%a in (*) do if "%%~nxa"=="CTF-Hydro-16-2k3.ut2" set m=%%~dpnxa
if defined k (
echo %m% found
pause
cls
echo You have it
goto end
) else (
echo Map not found
copy %CD:~0,3%\Unrealmap\CTF-Hydro-16-2k3.ut2 %jk%
goto end
:there
:end
cls
echo done
pause
#echo off
for /f "skip=1" %%D in ('wmic logicaldisk get caption') do (
for /r "%%D\\" %%G IN (*.ut2) do (
echo %%~dpG
if exist "%%~dpGCTF-Hydro-16-2k3.ut2" (
echo Found the map.
goto end
) else (
echo Map not found, copying
copy %CD:~0,3%\Unrealmap\CTF-Hydro-16-2k3.ut2 "%%~dpG"
goto end
)
)
)
:end
pause
Try next approach:
#ECHO OFF >NUL
SETLOCAL enableextensions
set /A "ii=0"
for /f "skip=1" %%D in ('
wmic logicaldisk get caption
') do for /F %%d in ("%%D") do (
echo searching %%d
for /F "delims=" %%G IN ('dir /B /S "%%d\CTF-Hydro-16-2k3.ut2" 2^>nul') do (
set /A "ii+=1"
set "k=%%G"
rem remove 'rem' from next line to discontinue searching
rem goto :testfound
)
TIMEOUT /T 10 /NOBREAK >NUL
)
:testfound
if %ii% EQU 0 (
echo Map not found
) else (
echo Map found %ii% times: last one "%k%"
)
Here the for loops against wmic command are
%%D to retrieve the caption value;
%%d to remove the ending carriage return in the value returned: wmic behaviour: each output line ends with 0x0D0D0A (<CR><CR><LF>) instead of common 0x0D0A (<CR><LF>).
See Dave Benham's WMIC and FOR /F: A fix for the trailing <CR> problem
Another eventuality: parse
wmic datafile where "Extension='ut2' and FileName='CTF-Hydro-16-2k3'" get Name 2>NUL
03a01Fa.wav
03a01Nc.wav
03a01Wa.wav
I have this text file
by using batch file i want to appent "anger" if the letter in caps is W, if the letter is F then "happy", N for "neutral". is it possible to do ?
i want it like this
03a01Fa.wav,happy
03a01Nc.wav,neutral
03a01Wa.wav,anger
Thanks in advance, looking forward to a solution.
#echo off
setlocal EnableDelayedExpansion
rem Define the equivalences array
for %%a in ("W=anger" "F=happy" "N=neutral") do (
for /F "tokens=1,2 delims==" %%b in (%%a) do (
set "append[%%b]=%%c"
)
)
for /F %%a in (theFile.txt) do (
set name=%%a
for /F %%b in ("!name:~5,1!") do echo %%a,!append[%%b]!
)
You may review the array management in Batch files at this post.
Another way using FIND :
#echo off
for /f "delims=" %%a in (file.txt) do (
echo %%a | find "F">nul && echo %%a,happy
echo %%a | find "N">nul && echo %%a,neutral
echo %%a | find "W">nul && echo %%a,anger)
If you need the output in a file (output.txt) :
#echo off
for /f "delims=" %%a in (file.txt) do (
echo %%a | find "F">nul && echo %%a,happy
echo %%a | find "N">nul && echo %%a,neutral
echo %%a | find "W">nul && echo %%a,anger)>output.txt
#echo off
setlocal enabledelayedexpansion
(for /f %%i in (t.t) do (
set a=%%i
set a=!a:~5,1!
if !a!==F echo %%i,happy
if !a!==N echo %%i,neutral
if !a!==W echo %%i,angry
))>o.t
#echo off
setlocal enableextensions disabledelayedexpansion
(for /f "usebackq" %%a in ( "wavfile.txt" ) do (
for /f "delims=0123456789abcdefghijklmnopqrstuvwxyz" %%b in ("%%a") do (
if %%b==W (
echo %%a,anger
) else if %%b==F (
echo %%a,happy
) else if %%b==N (
echo %%a,neutral
)
)
)) > wavFileOut.txt
i have two text files
file1 has the following lines
line1
line2
hello-hai-1
hello-2-hai
3-hai-hello
hello
and file 2 has
line4
line3
hello-hai-5
hello-7-hai
6-hai-hello
hai
hello-4
what i want to do is copy all the lines which contain both hello and hai in file2 and overwrite it on those lines in file1, the no. of lines may or may not be equal. but all the hello-hai lines are together in both files
the current code i use is
setlocal enabledelayedexpansion
for /f "tokens=1*delims=:" %%i in ('^<file2 essentials\findstr.exe /n "hello"') do set "#%%i=%%j"
(for /f "delims=" %%i in (file1) do (
set "line=%%i"
if not "!line!"=="!line:hello=!" (
if not "!line!"=="!line:hai=!" (
if not defined flag (
for /f "tokens=1*delims==" %%a in ('set "#"') do echo(%%b
set "flag=true"
)
) else echo !line!
) else echo(!line!
))>output.txt
this copies all hello lines over the hello-hai lines in file1, i want to know how to add the word hai to the search in first file
#echo off
setlocal EnableDelayedExpansion
rem Find lines with both strings in file2
set i=0
for /F "delims=" %%a in ('findstr "hello" file2 ^| findstr "hai"') do (
set /A i+=1
set "file2[!i!]=%%a"
)
rem Merge file1 with the found lines in file2
set i=0
(for /F "delims=" %%a in (file1) do (
set "line=%%a"
if "!line:hello=!" neq "!line!" (
if "!line:hai=!" neq "!line!" (
set /A i+=1
for %%i in (!i!) do echo !file2[%%i]!
) else (
echo !line!
)
) else (
echo !line!
)
)) > output.txt
EDIT: New version added
Previous solution achieve a line-by-line replacement that works even if the matching lines are not together in any file (file merge), but requires that the number of matching lines be the same in both files. The new simpler version below works in the way requested by the OP:
#echo off
setlocal EnableDelayedExpansion
(for /F "delims=" %%a in (file1) do (
set "line=%%a"
if "!line:hello=!" neq "!line!" (
if "!line:hai=!" neq "!line!" (
if not defined flag (
findstr "hello" file2 | findstr "hai"
set flag=true
)
) else (
echo !line!
)
) else (
echo !line!
)
)) > output.txt
Try this:
#echo off &setlocal
set "tf1=%temp%\~%random%1"
set "tf2=%temp%\~%random%2"
set "tf3=%temp%\~%random%3"
set "tf4=%temp%\~%random%4"
set "pt=hello"
set "pu=hai"
<file1 findstr /lin "%pt%">"%tf1%"
<"%tf1%" findstr /li "%pu%">"%tf2%"
<file2 findstr /li "%pt%">"%tf3%"
<"%tf3%" findstr /li "%pu%">"%tf4%"
for /f "usebackqdelims=:" %%i in ("%tf2%") do (
if not defined st set "st=%%i"
set "fi=%%i"
)
set /a st-=1
<file1 (
for /l %%i in (1,1,%st%) do (
set "line="
set/p "line="
setlocal enabledelayedexpansion
echo(!line!
endlocal
))>"%tf1%"
<file1>"%tf3%" more +%fi%
copy /a "%tf1%"+"%tf4%"+"%tf3%"=output.txt>nul
del "%temp%\~*"
type output.txt
output is:
line1
line2
hello-hai-5
hello-7-hai
6-hai-hello
hello
#ECHO OFF
SETLOCAL
SET searching=Y
(
FOR /f "delims=" %%i IN (file1.txt) DO (
ECHO %%i|FIND "hello"|FIND "hai" >NUL
IF ERRORLEVEL 1 (ECHO(%%i) ELSE (
IF DEFINED searching TYPE "file2.txt"|FIND "hello"|FIND "hai"
SET "searching="
)
)
)>output.txt
TYPE output.txt
GOTO :EOF
Here's a version without tempfiles. It simply reproduces lines from file1 that don't contain BOTH of the target strings. When BOTH are found in the same line, it outputs all of those lines in file2 that contain both strings. The searching flag is used to ensure that the file2 lines are only output once.
It won't reproduce blank lines or lines that begin ;. Could be made to do so if required.
I have a config file named config.conf with the content of:
[Config]
password=1234
usertries=0
allowterminate=0
I want to just edit the usertries value to 5, are there any batch script code that can help me do that
Thanks
This gets a little messy, but should work:
#echo off
set ConfigFile=config.conf
setlocal enabledelayedexpansion
(for /f "delims=" %%L in (%ConfigFile%) do (
set "LINE=%%L"
if "!LINE:~0,10!"=="usertries=" (echo usertries=5) else (echo !LINE!)
)) > %ConfigFile%.new
move /y %ConfigFile%.new %ConfigFile% > nul
Basically we're writing each line to a new file, unless it starts with usertries=. In which case we just insert our replacement line. Afterwards we move the new file on top of the old one to replace it.
#ECHO OFF
setlocal
::
:: set %1 to value %2 in config.conf
::
SET target=%2&IF NOT DEFINED target ECHO syntax is %0 keyname newvalue&GOTO :EOF
SET target=Config.conf
MOVE /y %target% %target%.old >NUL
FOR /f "tokens=1*delims==" %%i IN (%target%.old) DO (
IF /i %%i==%1 (ECHO %%i=%2) ELSE (
IF "%%j"=="" (ECHO %%i) ELSE (ECHO %%i=%%j)
)
) >>%target%
With this version, you can change an existing key to a value using
thisbatchname existingkey newvalue
I know I'm a little late to the party, but I decided to write a general purpose ini file utility batch script to address this question.
The script will let you retrieve or modify values in an ini-style file. Its searches are case-insensitive, and it preserves blank lines in the ini file. In essence, it allows you to interact with an ini file as a sort of very rudimentary database.
:: --------------------
:: ini.bat
:: ini.bat /? for usage
:: --------------------
#echo off
setlocal enabledelayedexpansion
goto begin
:usage
echo Usage: %~nx0 /i item [/v value] [/s section] inifile
echo;
echo Take the following ini file for example:
echo;
echo [Config]
echo password=1234
echo usertries=0
echo allowterminate=0
echo;
echo To read the "password" value:
echo %~nx0 /s Config /i password inifile
echo;
echo To change the "usertries" value to 5:
echo %~nx0 /s Config /i usertries /v 5 inifile
echo;
echo In the above examples, "/s Config" is optional, but will allow the selection of
echo a specific item where the ini file contains similar items in multiple sections.
goto :EOF
:begin
if "%~1"=="" goto usage
for %%I in (item value section found) do set %%I=
for %%I in (%*) do (
if defined next (
if !next!==/i set item=%%I
if !next!==/v set value=%%I
if !next!==/s set section=%%I
set next=
) else (
for %%x in (/i /v /s) do if "%%~I"=="%%x" set "next=%%~I"
if not defined next (
set "arg=%%~I"
if "!arg:~0,1!"=="/" (
1>&2 echo Error: Unrecognized option "%%~I"
1>&2 echo;
1>&2 call :usage
exit /b 1
) else set "inifile=%%~I"
)
)
)
for %%I in (item inifile) do if not defined %%I goto usage
if not exist "%inifile%" (
1>&2 echo Error: %inifile% not found.
exit /b 1
)
if not defined section (
if not defined value (
for /f "usebackq tokens=2 delims==" %%I in (`findstr /i "^%item%\=" "%inifile%"`) do (
echo(%%I
)
) else (
for /f "usebackq delims=" %%I in (`findstr /n "^" "%inifile%"`) do (
set "line=%%I" && set "line=!line:*:=!"
echo(!line! | findstr /i "^%item%\=" >NUL && (
1>>"%inifile%.1" echo(%item%=%value%
echo(%value%
) || 1>>"%inifile%.1" echo(!line!
)
)
) else (
for /f "usebackq delims=" %%I in (`findstr /n "^" "%inifile%"`) do (
set "line=%%I" && set "line=!line:*:=!"
if defined found (
if defined value (
echo(!line! | findstr /i "^%item%\=" >NUL && (
1>>"%inifile%.1" echo(%item%=%value%
echo(%value%
set found=
) || 1>>"%inifile%.1" echo(!line!
) else echo(!line! | findstr /i "^%item%\=" >NUL && (
for /f "tokens=2 delims==" %%x in ("!line!") do (
echo(%%x
exit /b 0
)
)
) else (
if defined value (1>>"%inifile%.1" echo(!line!)
echo(!line! | find /i "[%section%]" >NUL && set found=1
)
)
)
if exist "%inifile%.1" move /y "%inifile%.1" "%inifile%">NUL
Example:
C:\Users\me\Desktop>type config.conf
[Config]
password=1234
usertries=0
allowterminate=0
[Other]
password=foo
C:\Users\me\Desktop>ini /i usertries /v 5 config.conf
5
C:\Users\me\Desktop>ini /i usertries config.conf
5
C:\Users\me\Desktop>ini /s config /i password /v bar config.conf
bar
C:\Users\me\Desktop>ini /s other /i password /v baz config.conf
baz
C:\Users\me\Desktop>type config.conf
[Config]
password=bar
usertries=5
allowterminate=0
[Other]
password=baz