Batch File Recursively Identify and Copy to Other Multiple Directories - batch-file

I need to identify all files that begin with US_ within a folder, and then copy those to multiple numbered folders.
I'm using the following code for the copy, but cannot figure out how to identify the files to be copied. %ROOTPATH% has been define previously:
ECHO Which workstation are you copying user settings FROM?
SET /p WSFROM="Workstation Number?: "
ECHO Enter a range (eg. 5, eg. 10-15)
SET /p WSTO="Workstation Numbers?: "
for /f "usebackq delims=- tokens=1,2" %%a in ('%WSTO%') do (
set "LOWERWS=%%a"
set "UPPERWS=%%b"
)
if not "%UPPERWS%"=="" goto :copy_range
:copy_range
FOR /L %%i IN (%LOWERWS%, 1, %UPPERWS%) DO (
xcopy %ROOTPATH%\WORKSTATIONS\%WSFROM%\US_*.DAT %ROOTPATH%\WORKSTATIONS\%%i\US_*.DAT %%G)

This line should work with your code:
xcopy "%ROOTPATH%\WORKSTATIONS\%WSFROM%\US_*.DAT" "%ROOTPATH%\WORKSTATIONS\%%i\"

Related

Parse specific strings (2 strings) from multiple text files from a folder

I am trying to parse multiple lines which starts with:
Procedure = xxxxx::xxxx
Description = xxxxxx
Also, I want to ignore SH Library Procedure = $(Stem)_test which has same word Procedure in the .txt file.
I want to search all *.txt files and accumulate date in output file which I will use to upload in req management tool.
Here is the sample of the file:
Harness Lib Greenhills BLD Add Excluded Files = FALSE
Harness Lib Template Project File =
Harness Lib Generated Project File =
Harness Lib Generate Compiler Project File = FALSE
SH Library Procedure = $(Stem)_test
Harness Lib Source Lists Add Excluded Files = FALSE
Harness Lib Substitute Unused Source Files = FALSE
Macro Standard 1 = Set TBRUN_MACRO_STANDARD_1 in Testbed.ini
Procedure = sander_class::sander_class
Member Of = 1
Creation Date = Jun 21 2019 14:36:44
Description = This test is to verify that constructor is called. Req Tested: 67060-SWINTR-73
I have tried below code, but it does not print Procedure and in specific format.
#echo off
(
for /f "tokens=1,*" %%a in ('find "Procedure =" ^< "TEST.txt"') do (
for /f "tokens=1,*" %%d in ('find "Description =" ^< "TEST.txt"') do (
for /f "tokens=1,2 delims=#" %%c in ("%%b") do (
echo(Procedure %%~nxc
echo(
echo(Procedure %%a
echo(
echo(Description %%d
echo(
echo(Path: %%~pb
echo(
)
)
)>"output file.txt"
pause
I need output in below format for all the files (.txt) in same folder:
File Name =
Procedure = sander_class::sander_class
Description = This test is to verify that constructor is called. Req Tested: 67060-SWINTR-73
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q57185510.txt"
SET "outfile=%destdir%\outfile.txt"
(
FOR /f "tokens=*" %%a IN (
'findstr /R /b /C:" *Procedure =" /c:" *Description =" "%filename1%" '
) DO ECHO %%a
)>"%outfile%"
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances. The listing uses a setting that suits my system.
I used a file named q57185510.txt containing your data for my testing.
Produces the file defined as %outfile%
I used the one specific file for testing; for all files then set filename1 to a filemask like *.txt.
The findstr looks in all files matching filename1 for lines that /b begin with /r regular-expressions /c:"regex-string" the "regex-string". "regex" here is a small subset of regular expressions, but the particular expressions of interest are for instance Space(any number of)ProcedureSpace= which matches the two lines in question.
The tokens=* suppresses the leading spaces, producing the required lines.
Okay, This should do it but I can't test at the moment.
#(
ECHO OFF
SETLOCAL EnableDelayedExpansion
SET "_FilePath=C:\Admin"
SET "_FileGlob=*.txt"
SET "_MatchRegex1=Procedure =.*::.*$"
SET "_MatchRegex2=Description = .*::.*$"
SET "_ExcludeRegex=^SH Library Procedure =.*$"
SET "_OutputFile=%Temp%\output file.txt"
)
FOR /F "Tokens=*" %%A IN ('
DIR /A-D /S /B "%_FilePath%\%_FileGlob%"
') DO (
SET "_FileName=%%~nxA"
SET "_CurrentFile=!_FileName: =_!"
FOR /F "Tokens=1*" %%a IN ('
FindStr /I /R
/C:"%_MatchRegex1%"
/C:"%_MatchRegex2%"
"%%A"
^| FindStr /I /R /V
/C:"%_ExcludeRegex%"
') DO (
IF NOT DEFINED !_CurrentFile! (
SET "!_CurrentFile!=Found"
ECHO.File Name: !_FileName!
)
ECHO.%%a %%b
)
)>> "_OutputFile"
PAUSE
I will have to come back through and write up exactly what is being done in more detail if needed.
Essentially I am just using a loop of a DIR command to find all of the .txt files in all directories and subdirectories under the given path.
Then I parse that pull out the file name portion and create a variable I can use to match if the file has already been parsed before so that we only print the file name once.
I don't want to print file names at all unless a match was made because I don't think you care to see long lists of files with no matches, but if you prefer that the logic to test if the file name was found previously can be removed and you can just spit out the file name in the first loop
The second loop is looping the results of running a FindStr command on the given file found in the first loop and matching the Regexes which should mean at least two entries per file more if there are more procedures.
FindStr allows sRegex Matches and /V means to exclude any string that matches and pass the rest.

How to pull specific data from comma separated .txt file and apply it to a variable to use in command line switch

I have hundrends of subfolders with identical file structures. One of the files in each folder is a metadata.txt file that contains comma separated information. I need to pull the 8th value and asign it to a variable %x and then use that variable as a switch in a follow-up command.
The metadata.txt file looks like this:
91,Chocolate,10,Large,Easy Bake Oven,350,0,39.9475,Cake,1.0.0.1,C:\CakeRecords,2044449,2(10-50),1,
Step 1: Assign varariable x (%x) the 8th value in the data. In this case it's 39.9475
Step 2: Run EasyBake command using the variable as a switch
Example: EasyBake.exe 39.9475
I'll be running this command one time in the root folder and having it go through every subfolder to run the command in each of them. I've already run a command to create a new folder 'NewRecipe' in each of the subfolders, so I've got a decent idea on how to bounce between folders to run the scripts, but any advice would be appreciated there as well.
FOR /d %A IN ("N:\old recipes\*") DO mkdir "%A\NewRecipe"
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\metadata.txt"
FOR /f "delims=" %%a IN (
'dir /b /s /a-d "%filename1%" '
) DO (
FOR /f "usebackqtokens=8delims=," %%t IN ("%%a") DO (
ECHO take your choice
ECHO PUSHD "%%~dpa"
ECHO MD newrecipe
ECHO easybake.exe %%t
ECHO POPD
ECHO ================
)
)
GOTO :EOF
Simply shows the required instructions.
Find each of the target files, get the appropriate field to %%t, then do what you will with the appropriate elements of %%a

Batch: search for files with certain extension, owner, fullpath and last write access and output in CSV

I'm trying to create a CSV with fullpath\filename, file owner and last write access (modification date) of all txt and html files from all hard drives of a data server.
Here's what I got so far:
set pgm=%~n0
set log=%~dpn0.log
set host=%COMPUTERNAME%
set csv=%host%.csv
set dir=D:\BME
if not exist "%csv%" type nul>"%csv%"
for /f "delims=;" %%a in ('dir /b/s %dir%\*.txt, %dir%\*.html') do (
>>%csv% echo "%%a"
)
That outputs the path + filename of all found txt and html files of a certain folder in a CSV. I tried this command to get the hard drives:
wmic logicaldisk where drivetype=3 get caption
But I can't get my head around how to store that in a variable or file and loop through it and also retrieve the owner and last modification date and put it into a new column of the csv file.
I can't get my head around how to store that in a variable
Use the following batch file.
GetDrives.cmd:
#echo off
setlocal enabledelayedexpansion
rem skip=1 to remove the header
rem findstr to remove blank lines
for /f "skip=1" %%d in ('wmic logicaldisk where drivetype^=3 get caption ^| findstr /r /v "^$"') do (
set _drive=%%d
echo !_drive!
)
endlocal
Notes:
Be careful when using drivetype=3 as I have a removable drive of type 3. In the below output C: is a fixed hard disk and F: is a removable external USB drive.
Replace echo !_drive! as appropriate with a modified version of your existing code.
Example Output:
F:\test>GetDrives
C:
F:
F:\test>
Further Reading
An A-Z Index of the Windows CMD command line - An excellent reference for all things Windows cmd line related.
enabledelayedexpansion - Delayed Expansion will cause variables to be expanded at execution time rather than at parse time.
for /f - Loop command against the results of another command.
wmic - Windows Management Instrumentation Command.
DavidPostill answered how-to store wmic logicaldisk … output in a variable;
to retrieve file last modification date: use echo "%%a","%%~ta" in your script using %~t Parameter Extension;
to retrieve file owner: echo "%%a","%%~ta","!_owner!" where _owner variable comes from getRealOwner subroutine based on modified schletti2000's answer Get ownership information from command line by using wmic.
The script:
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "pgm=%~n0"
set "log=%~dpn0.log"
set "host=%COMPUTERNAME%"
set "csv=%host%.csv"
set "dir=D:\BME"
set "dirmask=%dir%\*.txt, %dir%\*.html"
rem if not exist "%csv%" type nul>"%csv%"
>"%csv%" (
for /f "delims=;" %%a in ('dir /b/s %dirmask% 2^>NUL') do (
set "_fFullPath=%%~a"
set "_fLastWrite=%%~ta"
set "_fOwner="
call :getRealOwner
SETLOCAL EnableDelayedExpansion
echo "!_fFullPath!","!_fOwner!","!_fLastWrite!"
ENDLOCAL
)
)
)
type "%csv%"
goto :continue
:getRealOwner
SET "ESCAPED=%_fFullPath:\=\\%"
SET "UNDELIMITED="
for /F "skip=2 delims=" %%g in ('
wmic path Win32_LogicalFileSecuritySetting where Path^="%ESCAPED%" ^
ASSOC /RESULTROLE:Owner /ASSOCCLASS:Win32_LogicalFileOwner ^
/RESULTCLASS:Win32_SID 2^>NUL
') do (
SET "UNDELIMITED=%%g"
call :process_wmioutput
)
if NOT defined UNDELIMITED set "_fOwner=???"
exit /B
:process_wmioutput
SET "DELIMITED=%UNDELIMITED: =•%"
FOR /F "delims=• tokens=10,12" %%G in ("%DELIMITED%") DO set "_fOwner=%%H\%%G"
exit /B
:continue
I used next settings to demonstrate various output:
set "dir=D:"
set "dirmask=%dir%\loc*.vbs %dir%\bcd*.log %dir%\act*.xsl %dir%\diag*.xml %dir%\chec*.csv"
Output - non-privileged cmd window:
==> D:\bat\SO\39034430.bat
"D:\odds and ends\tempx\links\testDJ\LocUsers.vbs","mypc\user","25.12.2014 00:13"
"D:\tempWin\ActivityLog.xsl","NT AUTHORITY\SYSTEM","24.02.2016 13:12"
"D:\tempWin\CompatTelemetryLogs\diagerr.xml","???","12.08.2015 03:17"
"D:\tempWin\CompatTelemetryLogs\diagwrn.xml","???","12.08.2015 03:17"
"D:\test\check_acl.csv","BUILTIN\Administrators","06.03.2016 14:28"
Output - privileged (run as administrator) cmd window:
=ADMIN=> D:\bat\SO\39034430.bat
"D:\odds and ends\tempx\links\testDJ\LocUsers.vbs","mypc\user","25.12.2014 00:13"
"D:\tempWin\ActivityLog.xsl","NT AUTHORITY\SYSTEM","24.02.2016 13:12"
"D:\tempWin\CompatTelemetryLogs\diagerr.xml","NT AUTHORITY\SYSTEM","12.08.2015 03:17"
"D:\tempWin\CompatTelemetryLogs\diagwrn.xml","NT AUTHORITY\SYSTEM","12.08.2015 03:17"
"D:\test\check_acl.csv","BUILTIN\Administrators","06.03.2016 14:28"

Random renaming all .exe files in a folder using batch

What I want to accomplish is to rename all the .exe that I have in a folder.
Sample of random name should be "589uday5xpsa9iz.exe"
I would appreciate any help I can get on this, I have been trying to figure it out for a couple of days now.
Try this :
#echo off
setlocal enabledelayedexpansion
:://The string length of the output
set $Lcode=16
set $#=#
:://The char Map
set $l="#0=0" "#1=a" "#2=B" "#3=c" "#4=d" "#5=E" "#6=f" "#7=g" "#8=H" "#9=I" "#10=j" "#11=K" "#11=1" "#13=2" "#14=3" "#15=4" "#16=5"
:://Evaluating the char MAP
for %%a in (%$l%) do set %%~a
:://Looping in the directory for .exe files
for /f "delims=" %%x in ('dir /b/a-d "*.exe"') do (
for /l %%a in (0,1,%$Lcode%) do (
call:rand
)
ECHO ren "%%x" !$Fstring!.exe
set $Fstring=
)
pause
exit/b
:://Getting the random Char
:rand
set /a $n=!random!%%17
set $Fstring=!$Fstring!!#%$n%!
I made a char MAP of just 15 char but you can increase it with all the char (up and downcase + number). If you do it. You have to increase the value in !random!%%17
with the value of the total CHAR map(+1).
You can increase the length of the random string by changing the value in the variable : $Lcode (16) in this example.
The output :
ren CnpjSdee.exe 2aHg5I22EBBE2ff5.exe
ren DbatchCnpj.exe EIIg2E54aHHIEgfHE.exe
ren NTStreamColor.exe jg03f3dIfBfIfHj2.exe
ren savedialog.exe EgfdajIcdc2cf03E.exe
Press any key to continue. . .
If it's OK Remove the ECHO to realy rename the files.
this is a simple batch that will work from within the folder that contains the files to be renamed you could make a shortcut to use it from the desk top. use copy and paste for long names. C:\Documents and Settings\Owner\Desktop\New Folder\Rename.bat (file = Rename.bat) don't use the whole path.
#echo off
title Rename Bat
echo This bat must be in the folder that
echo contains the files to be renamed.
:begin
echo Enter File Name
set /p old=
echo Enter New Name
set /p new=
ren "%old%" "%new%"
echo File Renamed
ping -n 3 127.0.0.1 >NUL
goto begin
hope this works for you.
a much simpler approach ... try a for loop that cycles through all files in that folder and renames them one at a time giving each a unique number ...
#echo off
for /L %%n in (1 1 %random%) do (
for %%a in (*.exe) do (
rename "%%a" "%%a_%%n.exe"
)
)
so %%a represents all the files in that folder and %%n represents the unique number that is going to be assigned to each file in the for body separated with _ symbol
to use this batch file you have to place it in the folder containing your .exe files
this would rename files to original name_1 then original name _2 and so on if you want it to be completely random use only %random% in bracket of the first for loop and do away with the iteration "1" (see below) also at the renaming part do away with %%a to omit the original name of file so that you remain with only random numbers also see below e.g
#echo off
for /L %%n in (%random%) do (
for %%a in (*.exe) do (
rename "%%a" "%%n.exe"
)
)
hope this helps .....

How to use batch job to add the file "create date" into all the files in a directory?

I have a folder that gets a new file added everyday to the folder with the same file name but incremental extension such as .001, .002, .003, etc. However, if there's no file within the folder it starts at .001 again.
The problem is they are all named the same and if I move them to another folder to archive them it would just overwrite the same file over and over again. I could create a folder each day with the date with only one file in it, but that seems a bit redundant.
Is there a way to look at the create date of each file and rename it to the create date?
I've gotten this far, but it looks like for this situation I have to use a static file name, how to loop through the entire directory?
SET filename = C:\test.001
FOR %%f IN (%filename%) DO SET filedatetime=%%~tf
rename c:\test.001 C:\test_%filedatetime%.txt
move C:\*.txt C:\archive\
this provides the correct sort order:
#echo off &setlocal disableDelayedExpansion
set "startfolder=%userprofile%\test"
cd /d "%startfolder%"
for %%a in (*) do (
for /f "delims=." %%b in ('wmic datafile where "name='%startfolder:\=\\%\\%%~a'" get lastmodified^|find "."') do (
echo(ren "%startfolder%\%%~a" "%%~b.txt"
)
)
Remove echo to get it working.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "targetdir=c:\sourcedir"
SET "destdir=c:\destdir"
PUSHD "%targetdir%"
FOR %%a IN (*.*) DO (
SET "timestamp=%%~ta"
SET "timestamp=!timestamp:/=_!
SET "timestamp=!timestamp::=_!
SET "timestamp=!timestamp:.=_!
SET "timestamp=!timestamp:,=_!
SET "timestamp=!timestamp: =_!
ECHO MOVE "%%a" "%destdir%\%%~na.!timestamp!"
)
GOTO :EOF
This should work with any file in the nominated target directory where the name does not include ! or ^.
The required MOVE commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO MOVE to MOVE to actually move the files. Append >nul to suppress report messages (eg. 1 file moved)
The gymnastics around timestamp are intende to replace /: with _ since these are illegal filename characters. Space., are similarly replaced - they're legal but often painful.
If you want the destination filename to be name.003.timestamp, remove the ~na from the destination name.
Try like this :
SET $path=The_path_who_contain_the_FILES
FOR /F "DELIMS=" %%f IN ('dir "%$path%" /a-d/b') DO (
SET filedatetime=%%~tf
move "%%~dpnxf" "C:\archive\test_%filedatetime%.txt")

Resources