Command Prompt Scripting - batch-file

This is going to be hard to explain, I'll try my best.
I'm using a shell scripting (Test Executor) in command prompt to automate our regression testing. However i'm stuck on one thing.
Basically I have to copy this dynamically created folder in a location into another folder after the automated script is done (in CMD via scripting)
:: create an achieve directory
#SET ACHIEVE_DIR=C:\Test Result\LOG_Files
mkdir "%ACHIEVE_DIR%"
xcopy /y /s /e "%TEST_SOURCE_DIR%"\*.* "%ACHIEVE_DIR%"
This will copy all the files in the TEST_SOURCE_DIR, but i only want this dynamically created folder which changes according to the date stamp (BUT this date stamp is calculated by second - so i can't use that as a variable).
For example: After i run a test it'll create a folder under lets say C:\temp\ another folder named "TEST RUN - _2014-06-30 15_48_01_"
So if go into C:\temp i'll find a folder named "TEST RUN - _2014-06-30 15_48_01_" along with other folders. BUT i only want to copy this dynamic folder into Test Result\LOG_Files
What we are given is that the starting string will always be "TEST RUN -" but the ending string will interchange according to the time to the second (BUT we cannot go by that since it is the second of the starting test result).
I found out if i am in command prompt and i type in "cd TEST RU" and hit tab it'll finish it for me "cd TEST RUN - _2014-06-30 15_48_01_" Is there a way to script this tab hit or something?
Thanks!

This should work in a batch file to isolate the folder:
If there are a number of folders starting with test run - then tell us.
#echo off
SET "ACHIEVE_DIR=C:\Test Result\LOG_Files"
cd /d "c:\temp"
for /d %%a in ("test run -*") do xcopy "%%a\*.*" "%ACHIEVE_DIR%\" /s/h/e/k/f/c
This code looks for a test folder as discussed in the comments:
#echo off
SET "ACHIEVE_DIR=C:\Test Result\LOG_Files"
cd /d "c:\temp"
for /d %%a in ("test run -*") do (
pushd "%%a"
for /d /r %%b in ("test*") do (
xcopy "%%b\*.*" "%ACHIEVE_DIR%\" /s/h/e/k/f/c
)
popd
)

This batch file should do the job:
#echo off
rem Find the directory starting with "TEST RUN -" created last in C:\Temp.
set ACHIEVE_DIR=C:\Test Result\LOG_Files
for /F "usebackq delims=" %%D in ( `dir "C:\Temp\TEST RUN -*" /AD /B /O-D /TC` ) do (
set TEST_SOURCE_DIR=%%D
goto CopyDir
)
echo No directory starting with "TEST RUN -" found in C:\Temp.
pause
exit /b
:CopyDir
rem Copy all files and subdirectories from last test run to achieve
rem directory whereby xcopy automatically creates the achieve directory.
xcopy /E /I /Q /S /Y "%TEST_SOURCE_DIR%" "%ACHIEVE_DIR%"
set ACHIEVE_DIR=
set TEST_SOURCE_DIR=
Read the Microsoft pages about
dir
for
xcopy
for details about the used parameters of those 3 commands.
Or execute in a command prompt window the commands
dir /?
for /?
xcopy /?
one after the other to get the shorter help for those 3 commands output in the window.

Related

possible? seek *partially known* folder name - split to variable - insert/execute in robocopy *destination*

I use gallery-dl to download pics from Pixiv.com. All of the below are run from Windows' .bat files.
I manually create a folder with only {user[id]}.
Example: Pixiv - Temp\24517
I then copy gallery-dl.bat (which calls on gallery-dl.exe and the related gallery-dl.conf, elsewhere) and a number of assisting .jpg files into that folder.
Example: Pixiv-Temp\24517\gallery-dl.bat
I've done this for over 5,000 users.
Running gallery-dl.bat from within folder configured for the below, passing a variable of the folder name will download the pics as well as saving a *.sqlite3 file to the folder 24517.
gallery-dl.conf
"directory": ["{user[id]}"],
The actioning part of gallery-dl.bat (listed in whole, below).
"C:\Users\AdminS6\gallery-dl\gallery-dl.exe" -d "..\..\." --download-archive "%~dp0GDB.sqlite3" "https://www.pixiv.net/en/users/%FOLDER%/illustrations"
The current .bat file in whole:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0" || exit /B
move /y "..\Folder2.jpg" "..\Folder.jpg"
for %%I in (..) do set "FOLDER=%%~nxI"
for /f "tokens=1 delims= " %%a in ("%FOLDER%") do set tmpFOLDER=%%a
"C:\Users\AdminS6\gallery-dl\gallery-dl.exe" -d "..\..\." --download-archive "%~dp0GDB.sqlite3" "https://www.pixiv.net/en/users/%FOLDER%/illustrations"
del "..\Folder3.jpg"
if not exist "GDB.sqlite3" move /Y "..\Folder4.jpg" "..\Folder.jpg"
if exist "GDB.sqlite3" del "..\Folder4.jpg" && del "..\Folder.jpg"
if exist "..\*.mp4" md "..\Reels" & move /y "..\*.mp4" "..\Reels\"
if exist "..\*.gif" md "..\GIFs" & move /y "..\*.gif" "..\GIFs\"
if exist "..\*.webp" md "..\WEBPs" & move /y "..\*.webp" "..\WEBPs\"
robocopy "..\..\%FOLDER%" "X:\11Web\gallery-dl\Pixiv - Temp\24517 -" *.* /e /move
TIMEOUT /T 1
popd
endlocal
I now plan to change gallery-dl.conf to {user[id]} - {user[name]}. This will result in a change to the destination folder being created now by gallery-dl. The original folder is left unchanged.
Example my original source folder: Pixiv-Temp\24517
Example gallery-dl new output folder: Pixiv-Temp\24517 - ケースワベ
gallery-dl.conf
"directory": ["{user[id]} - {user[name]}"],
gallery-dl.exe
"C:\Users\AdminS6\gallery-dl\gallery-dl.exe" -d "..\..\." --download-archive "%~dp0GDB.sqlite3" "https://www.pixiv.net/en/users/%FOLDER%/illustrations"
Not knowing how a {user[name]} will come out in Explorer folder naming, I am left to still manually create an original source folder with only {user[id]}. I will continue doing this due to ease.
The above noted change will present problems I would like to overcome:
When running gallery-dl, the pics from Pixiv will be downloaded to an Explorer folder name of {user[id]} - {user[name]}, while the original manually-created folder still hosts the gallery-dl and *.sqlite3 file. I need these combined.
When re-running/updating gallery-dl against the 5,000+ other folders, I will be left with 5,000 of one {user[id]} and 5,000 of the other {user[id]} - {user[name]}.
Robocopy has shown the most promise in solving these. When run in the below .bat, gallery-dl runs and all files from {user[id]} folder are moved to {user[id]} - {user[name]} folder, leaving {user[id]} folder empty and I just run a script that deletes all empty folders. This has the added benefit that the .sqlite3 files are all moved.
MY ISSUE: I have not yet been successful with Robocopy without having to
explicitly name the path for the destination folder.
Example works:
robocopy "..\..\%FOLDER%" "X:\11Web\gallery-dl\Pixiv - Temp\24517 -" *.* /e /move
Example doesn't work:
robocopy "..\..\%FOLDER%" "..\..\24517 -" *.* /e /move
which after passing a second variable would look more like:
Example doesn't work:
robocopy "..\..\%FOLDER%" "..\..\%FOLDERDESTINATION%" *.* /e /move
nor
I have no idea how to pass a variable from a folder name that is not known in advance {user[id]} - {user[name]}, but must be searched for within the above root folder.
If there was a way from within the .bat file to
Declare a variable that matches the current folder {user[id]} (Already done in the below).
Example: 24517
and
And gallery-dl creates the new {user[id]} - {user[name]} and done its business, the .bat find and declare a variable that matches "{user[id]} -".
Example: 24517 - ケースワベ
As such, I will always know the first half of any variable:
{user[id]} -
or in this case
24517 -
Question is can the entire new folder name be searched for based on the known (Example 24517 -), a suitable secondary variable created equating to the new folder name, from only that?
And is then able to pass this variable to Robocopy in order to successfully move all desired files?
Example:
robocopy "..\..\%FOLDER%" "..\..\%FOLDERDESTINATION%" *.* /e /move
That would be just smashing!
Any and all ideas/assistance are appreciated. Thank you in advance!
Final result after applying successful answer from Stephan
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0" || exit /B
move /y "..\Folder2.jpg" "..\Folder.jpg"
for %%I in (..) do set "FOLDER=%%~nxI"
for /f "tokens=1 delims= " %%a in ("%FOLDER%") do set tmpFOLDER=%%a
"C:\Users\AdminS6\gallery-dl\gallery-dl.exe" -d "..\..\." --download-archive "%~dp0GDB.sqlite3" "https://www.pixiv.net/en/users/%FOLDER%/illustrations"
del "..\Folder3.jpg"
if not exist "GDB.sqlite3" move /Y "..\Folder4.jpg" "..\Folder.jpg"
if exist "GDB.sqlite3" del "..\Folder4.jpg" && del "..\Folder.jpg"
if exist "..\*.mp4" md "..\Reels" & move /y "..\*.mp4" "..\Reels\"
if exist "..\*.gif" md "..\GIFs" & move /y "..\*.gif" "..\GIFs\"
if exist "..\*.webp" md "..\WEBPs" & move /y "..\*.webp" "..\WEBPs\"
for /d %%a in ("..\..\%FOLDER% - *") do set "FOLDERDESTINATION=%%a"
rem ECHO %FOLDERDESTINATION%
robocopy "..\..\%FOLDER%" ".\%FOLDERDESTINATION%" *.* /e /move
TIMEOUT /T 1
popd
endlocal
When I understood your question right, this should help:
for /d %%a in ("..\..\%folder% - *") do set "folderdestination=%%a"
(Assumption: there is just one username per %folder% - else this will get only the last of them)

Batch Script to copy folder from Server to user desktop in a network

My goal is to create a batch script to copy a folder with subfolders to user desktop with overwrite option and minimized of command prompt.
I am pushing the script through Group policy in user start up screen.
However I am getting an error when running the script locally. Not sure what I am missing in the script..
#echo off
#cls
if not "%minimized%"=="" goto :minimized
set minimized=true
start /min cmd /C "%~dpnx0"
goto :EOF
:minimized
echo Your Source Path:
set INPUT1=\\X.X.X.X\Test\TMS\
echo Your Destination Path:
set INPUT2=C:\Users\%Username%\Desktop\
xcopy %INPUT1% %INPUT2% /y /s
:minimized
You mentioned folder, so I am writing this assuming you want to create the TMS folder with content on the desktop.
I would try something like this inside of you minimized label. This is untested as I have no Network drives to test with.
for /f "tokens=2" %i in ('net use * "\\X.X.X.X\Test\TMS\" ^| findstr /i Drive') do set "tmpDr=%%i"
mkdir "%USERPROFILE%\Desktop\TMS" >nul
xcopy "%tmpDir%\*" "%USERPROFILE%\Desktop\TMS" /s /y
net use /d %tmpDir% >nul
Some things to note in your code. You have 2 minimized labels, you need to enclose path variables with double quotes to eliminate possible whitespace, you can drop the echo's seeing as you plan on running the script minimized. Last but not least, you do not need to specify full path to the user's desktop as %USERPROFILE% variable already exists as Drive:\Users\Username

How to compress each subfolder in a folder into a separate RAR archive using WinRAR?

I am really new to batch file coding and need your help.
I've these directories:
c:\rar\temp1\xy.jpg
c:\rar\temp1\sd.jpg
c:\rar\temp1\dd.jpg
c:\rar\temp2\ss.jpg
c:\rar\temp2\aa.jpg
c:\rar\temp2\sd.jpg
c:\rar\temp3\pp.jpg
c:\rar\temp3\ll.jpg
c:\rar\temp3\kk.jpg
And I want to compress them to this
c:\rar\temp1\temp1.rar
c:\rar\temp2\temp2.rar
c:\rar\temp3\temp3.rar
How could this be done using WinRAR?
This can be done also with WinRAR without using a batch file, not exactly as requested, but similar to what is wanted.
Start WinRAR and navigate to folder c:\rar\.
Select the folders temp1, temp2 and temp3 and click on button Add in the toolbar.
As archive name specify now the folder for the RAR archives, for example c:\rar\.
Switch to tab Files and check there the option Put each file to separate archive.
Click on button OK.
WinRAR creates now three RAR archives with the file names temp1.rar, temp2.rar and temp3.rar in folder c:\rar\ with each archive containing the appropriate folder with all files and subfolders.
The list of files to add can be changed also on tab Files by entering for example *.txt in Files to exclude to ignore text files in the three folders on creating the archives.
And finally it makes sense to enter *.jpg on tab Files in edit field below Files to store without compression as JPEG files usually contain already compressed data and therefore WinRAR cannot really compress the data of the files further.
Here is also a batch file solution to move the files in all non-hidden subfolders of c:\rar\ and their subfolders into an archive file with name of the subfolder created in each subfolder as requested.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "RAREXE=Rar.exe"
if exist "%RAREXE%" goto CreateArchives
if exist "%ProgramFiles%\WinRAR\Rar.exe" set "RAREXE=%ProgramFiles%\WinRAR\Rar.exe" & goto CreateArchives
if exist "%ProgramFiles(x86)%\WinRAR\Rar.exe" set "RAREXE=%ProgramFiles(x86)%\WinRAR\Rar.exe" & goto CreateArchives
for /F "skip=2 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe query "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe" /v Path 2^>nul') do (
if /I "%%I" == "Path" if exist "%%~K\Rar.exe" for %%L in ("%%~K\Rar.exe") do set "RAREXE=%%~fL" & goto CreateArchives
)
for /F "skip=2 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe query "HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe" /v Path 2^>nul') do (
if /I "%%I" == "Path" if exist "%%~K\Rar.exe" for %%L in ("%%~K\Rar.exe") do set "RAREXE=%%~fL" & goto CreateArchives
)
for /F "delims=" %%I in ('%SystemRoot%\System32\where.exe Rar.exe 2^>nul') do set "RAREXE=%%I" & goto CreateArchives
echo ERROR: Could not find Rar.exe!
echo/
echo Please define the variable RAREXE at top of the batch file
echo "%~f0"
echo with the full qualified file name of the executable Rar.exe.
echo/
pause
goto :EOF
:CreateArchives
set "Error="
for /D %%I in ("c:\rar\*") do (
echo Creating RAR archive for "%%I" ...
"%RAREXE%" m -# -cfg- -ep1 -idq -m3 -msgif;png;jpg;rar;zip -r -s- -tl -y -- "%%I\%%~nxI.rar" "%%I\"
if errorlevel 1 set "Error=1"
)
if defined Error echo/& pause
endlocal
The lines after set "RAREXE=Rar.exe" up to :CreateArchives can be omitted on definition of environment variable RAREXE with correct full qualified file name.
Please read the text file Rar.txt in the WinRAR program files folder for an explanation of RAR command m and the used switches. The question does not contain any information with which options the RAR archives should be created at all.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains %~f0 ... full name of batch file
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg /?
reg query /?
set /?
setlocal /?
where /?
See also single line with multiple commands using Windows batch file for an explanation of the operator &.
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on the three FOR command lines to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded reg or where command line with using a separate command process started in background.
This script can work as well:
#echo off
for %%a in ("C:\rar\temp1" "C:\rar\temp2" "C:\rar\temp3") do (
pushd "%%~a"
"C:\Program Files\WinRAR\rar.exe" a -r temp.rar *
popd
)
In Python v3.x:
Tested on Python v3.7
Tested on Windows 10 x64
import os
# NOTE: Script is disabled by default, uncomment final line to run for real.
base_dir = "E:\target_dir"
# base_dir = os.getcwd() # Uncomment this to run on the directory the script is in.
# Stage 1: Get list of directories to compress. Top level only.
sub_dirs_raw = [os.path.join(base_dir, o) for o in os.listdir(base_dir) if os.path.isdir(os.path.join(base_dir, o))]
# Stage 2: Allow us exclude directories we do not want (can omit this entire section if we wish).
dirs = []
for d in sub_dirs_raw:
if "legacy" in d or "legacy_old" in d:
continue # Skip unwanted directories
print(d)
dirs.append(d)
# Stage 3: Compress directories into .rar files.
for d in dirs:
os.chdir(d) # Change to target directory.
# Also adds 3% recovery record using "-rr3" switch.
cmd = f"\"C:\Program Files\\WinRAR\\rar.exe\" a -rr3 -r {d}.rar *"
print(cmd)
# Script is disabled by default, uncomment this next line to execute the command.
# os.system(cmd)
Notes:
Script will do nothing but print commands, unless the final line os.system(cmd) is uncommented by removing the leading # .
Run the script, it will print out the DOS commands that it will execute. When you are happy with the results, uncomment final line to run it for real.
Example: if there was a directory containing three folders mydir1, mydir2, mydir3, it would create three .rar files: mydir1.rar, mydir2.rar, mydir3.rar.
This demo code will skip directories with "legacy" and "legacy_old" in the name. You can update to add your own directories to skip.
To execute the script, install Python 3.x, paste the lines above into script.py, then run the DOS command python script.py from any directory. Set the target directory using the second line. Alternatively, run the script using PyCharm.
This should work it also checks if the files were compressed alright.
You may need to change this part "cd Program Files\WinRAR" depending on where winrar is installed.
#echo Off
Cd\
cd Program Files\WinRAR
rar a -r c:\rar\temp1\temp1.rar c:\rar\temp1\*.jpg c:\rar\temp1\
if "%ERRORLEVEL%"=="0" ( Echo Files compressed
) Else Echo Failed
rar a -r c:\rar\temp2\temp2.rar c:\rar\temp2\*.jpg c:\rar\temp2\
if "%ERRORLEVEL%"=="0" ( Echo Files compressed
) Else Echo Failed
rar a -r c:\rar\temp3\temp3.rar c:\rar\temp3\*.jpg c:\rar\temp3\
if "%ERRORLEVEL%"=="0" ( Echo Files compressed
) Else Echo Failed
Pause
Below Script will compress each folder as a RAR file within the current directory with very useful info while compressing a large size of data.
#echo off
#for /D %%I in (".\*") do echo started at %date% %time% compressing... "%%I" && #"%ProgramFiles%\WinRAR\Rar.exe" a -cfg- -ep1 -inul -m5 -r -- "%%I.rar" "%%I\"
echo "Completed Successfully !!!"
pause

adding dates to copied files

I am trying to add the dates to copied files from one directory to another directory. This is how it should look like
Original file name: XEsalary.csv
Result file name: XEsalary-2013-02-15.csv
Here is my code:
set REMOTE=U:\
set LOG=C:\Integration\FE\log_test
set PVM=%DATE:~9,4%-%DATE:~6,2%-%DATE:~3,2%
set YY=%DATE:~9,4%
set LOCAL=C:\FTP\VC\test
cd %LOCAL%
xcopy /y /f /v "%LOCAL%\*.csv" "%REMOTE%\" >>%LOG%\%PVM%.log
xcopy /y /f /v "%LOCAL%\*.csv" "%LOCAL%\archive\*.csv"
:: assist with turning this into a for loop
ren %LOCAL%\archive\*.csv %LOCAL%\archive\*%PVM%.csv
echo. >>%LOG%\%PVM%.log
copying works just file. It is the renaming part which is not working. Any help please?
Thx in advance :-)
Using wildcards with RENAME is tricky. There is no good official documentation, but I have experimented and published rules as to how it works: See How does the Windows RENAME command interpret wildcards?
You can accomplish your rename with the following command, as long as none of your file names include dots (the last extension dot is OK).
ren "%LOCAL%\archive\*.csv" ????????????????????-%PVM%*
The number of ? must be greater than or equal to the longest name in the folder.
The result will be incorrect if a file name contains a dot. For example, part1.part2.csv would become part1-2013-02-15.part2.csv.
Another option is to use a FOR loop. You can safely append the date to any file using this technique.
for %%F in ("%LOCAL%\archive\*.csv") do ren "%%F" "%%~nF-%PVM%%%~xF"
BUT, both solutions have a problem if you rerun the process on a later date. New files will be added to the archive, but both new and old archive files will be renamed to the current date. That won't work.
Better to copy and rename the file in one step using a FOR loop as suggested in rojo's answer.
Or better yet, create a new archive folder with the date in the folder name, and then copy the files to the dated archive folder without renaming :-)
set REMOTE=U:\
set LOG=C:\Integration\FE\log_test
set PVM=%DATE:~9,4%-%DATE:~6,2%-%DATE:~3,2%
set YY=%DATE:~9,4%
set LOCAL=C:\FTP\VC\test
cd %LOCAL%
xcopy /y /f /v "%LOCAL%\*.csv" "%REMOTE%\" >>%LOG%\%PVM%.log
md "%LOCAL%\archive\%PMV%
xcopy /y /f /v "%LOCAL%\*.csv" "%LOCAL%\archive\%PVM%"
You might want to include the time in the folder name if the process could be run multiple times in the same day.
Windows doesn't let you rename with a wildcard. You have to name each file in a for loop. Might as well do the renaming as you're copying. Does this do what you intended?
#echo off
setlocal
set REMOTE=U:\
set LOG=C:\Integration\FE\log_test
set PVM=%DATE:~9,4%-%DATE:~6,2%-%DATE:~3,2%
set YY=%DATE:~9,4%
set LOCAL=C:\FTP\VC\test
xcopy /y /f /v "%LOCAL%\*.csv" "%REMOTE%\" >>%LOG%\%PVM%.log
pushd "%LOCAL%"
for %%I in (*.csv) do (
rem Uncomment the following line to log the copy to archive.
rem echo copy "%%I" -^> "%LOCAL%\archive\%%~nI-%PVM%.csv" >>%LOG%\%PVM%.log
copy "%%I" "%LOCAL%\archive\%%~nI-%PVM%.csv">NUL
)
echo. >>%LOG%\%PVM%.log
popd

executing all the .reg files from batch file

I have following script that executes all the .reg files in the current directory. the problem is i also have sub directories in that folder and i want to execute those reg files as well. I am not sure what switch i am supposed to use. i tries using /s which returns all the .reg files of the drive.
this is how my batch file looks like:
rem #echo off
cls
SET folder=%~dp0
for %%i in ("%folder%*.reg") do (regedit /s "%%i")
echo done
pause
EXIT
This is how file/directory structure looks like:
Folder1
batchfile.bat -> user double clicks or executes from command prompt
1.reg
2.reg
3.reg
Folder2
4.reg
5.reg
what am i missing here?
I think that you need a recursive for loop using the /R switch:
for /R "%folder%" %%i in (*.reg) do (regedit /s "%%i")
You didn't actually say what your problem was, so instead of fixing your script here's what I would have done:
#echo off
set folder=%~dp0
for /f "usebackq" %%i in (`dir /s /b *.reg`) do (
regedit /s "%%i"
)
And the /s script on regedit is for silent mode. It tells regedit not to ask the user for confirmation with a dialog box. The for loop is what causes the batch file to loop through all subdirectories, not the /s switch on regedit.
From Microsoft's Knowledge Base:
[/s|-s]
When a filename is specified on the command line, this switch is used to
suppress any informational dialog boxes that would normally be displayed.
This is useful when the Setup program for an application wants to execute
REGEDIT.EXE with a .REG file, but does not want the user to be confused by
any dialog boxes that are displayed.

Resources