Batch File/Powershell - enumerating files in a folder - windows

Note: There is no need to use batch per say, but I am just familiar with batch, Powershell would be better I imagine, so if there are easier solutions for this problem in powershell, please shout!
I have the arduous task of testing our DR backups for all our clients, that is, mounting ShadowProtect Snapshots latest incremental, writing and reading a file, them unmounting the image. The actual ShadowProtect part of batch is fairly simple but I would like to design a batch that can automate this.
Essentially my question is:
How in a batch file can I firstly, enumerate files in a folder, and then place a specific part of a given filename into a variable?
Reason being ShadowProtect incrementals have a naming convention such like:
SERVERNAME_DRIVELETTER_b00X_i000x - whereby b = base image, i = incremental number
I need to mount the latest incremental image, therefore need to parse the folder and find the latest incremental image, based on the number following the i in the filename.
Is this possible in batch?
Thanks!

Something like this should work:
#echo off
setlocal EnableDelayedExpansion
for /f "delims=_ tokens=1-4" %%f in ('dir /b *_*_*_*') do (
set servername=%%f
set driveletter=%%g
set base_image=%%h
set increment=%%i
)
echo !servername!
echo !driveletter!
echo !base_image!
echo !increment!
endlocal
If you have several matching files and want to do something with all of them, you need to put the processing code inside the loop.
Edit:
for /f: process either a file or the output of a command enclosed in single quotes
delims=_: fields in the processed content are separated by underscores
tokens=1-4: assign the first four tokens to the parameters %%f through %%i (first parameter is the one given in the for statement)
dir /b *_*_*_*: list all file where the name contains at least 3 underscores with just their file name (the output of this command is processed by the for loop)
setlocal EnableDelayedExpansion: expand variables at run time (otherwise assigning the parameters to variables wouldn't work)
For further details see help for and help dir.

You could always use vbscript or jscript. It is much more powerful than batch files. Also jscript and vbscript hosts are available also on machines that don't have powershell!
Link for enumeration:
http://www.techimo.com/forum/webmastering-programming/100453-recursive-javascript-list-all-files-folders-given-folder.html
Jscript string reference:
http://msdn.microsoft.com/en-us/library/bxsyt3yc(v=vs.80).aspx
You should be able to combine the two.
you run your jscript (I prefer jscript to vbscript because of its resemblance to javascript)
cscript scriptname

Related

Trying to batch merge 2 .jpeg's horizontally and put them in a different folder after

this is for my doctoral thesis in medicine. So please excuse my noobishnis in programing.
I have a bunch (about 4000 files) of scans from patients. There is a front and a back .jpg for each patient. And there where multiple patients each day.
The folder structure looks like this:
\images
\2017-08-21
\pa_102165.jpg
\pa_10216500001.jpg
\2017-06-14
\pa_101545.jpg
\pa_10154500001.jpg
\pa_104761.jpg
\pa_10476100001.jpg
\pa_107514.jpg
\pa_10751400001.jpg
\2017-03-73
\pa_109631.jpg
\pa_10963100001.jpg
\pa_108624.jpg
\pa_10862400001.jpg
Where in the first example 2017-08-21 is the date the patient came in, pa_102165.jpg is the front and pa_10216500001.jpg is the back. So the front is always pa_10XXXX.jpg and the back is pa_10XXXX00001.jpg. I had no hand in the nameing scheme.
My goal is to make a batchscript that merges the 2 corresponding .jpgs of each patient horizontally and automatically puts them in a different folder, so that I don't have to do it manually with something like MS Paint.
For example like this:
\images
\merged
\2017-08-21
\pa_102165_merged.jpg
\2017-06-14
\pa_101545_merged.jpg
\pa_104761_merged.jpg
\pa_107514_merged.jpg
\2017-03-73
\pa_109631_merged.jpg
\pa_108624_merged.jpg
I'm working on Windows 10 and found two promising methods so far but fail to comprehend how to make this into a batch file or something like it.
IrfanView Thumbnails
1. Mark the 2 corresponding .jpgs
2. File>Create contact sheet from selected files...
3. Create
4. File>Save as... in destination folder which i have to create for every day
which is faster than merging them by hand but would consume multiple workdays to do for all the pairs
and...
ImageMagic in Windows cmd
C:\Users\me\doctor\Images\test\images\2016-03-31>convert pa_102165.jpg pa_10216500001.jpg +append pa_102165_merged.jpg
This produces the merged .jpeg in the same folder the input images are in. This looks more promising but I fail to grasp how I could automate this process given the nameing scheme and the folder structure.
Thanks for taking the time to read this! I'm happy for every input you have!
This should get you fairly close. Essentially it is using the power of the FOR command modifiers to extract the base file name and file extension. The FOR /F command is capturing the output of the DIR command that is piped to the FINDSTR command. We are doing that so we only grab files with the file mask of pa_######.jpg
Once we have that we use the command modifiers with the IF command to make sure the 00001 file exists. If it does exist then it will execute the convert command. For the sake of making sure the code is performing correctly I am just ECHOING the output to the screen. If the output on the screen looks correct then remove the ECHO so that the CONVERT command executes.
#echo off
CD /D "C:\Users\me\doctor\Images\test\images"
FOR /F "delims=" %%G IN ('DIR /A-D /B /S PA_*.jpg ^|findstr /RIC:"pa_[0-9][0-9][0-9][0-9][0-9][0-9]\.jpg$"') DO (
IF EXIST "%%~dpnG00001%%~xG" (
ECHO convert "%%G" "%%~dpnG00001%%~xG" +append "%%~dpnG_merged%%~xG"
)
)
This task could be done with IrfanView with the following batch file stored in the directory containing the folder images.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "IrfanView=%ProgramFiles(x86)%\IrfanView\i_view32.exe"
set "SourcePath=%~dp0images"
set "TargetPath=%~dp0merged"
for /F "delims=" %%I in ('%SystemRoot%\System32\where.exe /R "%SourcePath%" pa_10????.jpg 2^>nul') do for %%J in ("%%~dpI.") do (
if not exist "%TargetPath%\%%~nxJ\%%~nI_merged%%~xI" if exist "%%~dpnI00001%%~xI" (
if not exist "%TargetPath%\%%~nxJ\" md "%TargetPath%\%%~nxJ"
if exist "%TargetPath%\%%~nxJ\" (
echo Merging "%%~nxJ\%%~nxI" and "%%~nxJ\%%~nI00001%%~xI" ...
"%IrfanView%" /convert="%TargetPath%\%%~nxJ\%%~nI_merged%%~xI" /jpgq=95 /panorama=(1,"%%I","%%~dpnI00001%%~xI"^)
)
)
)
endlocal
There must be customized the fully qualified file name of IrfanView in the third line. There can be modified also the percent value of option /jpgq which defines the quality of the output JPEG file.
The command WHERE searches recursive in subdirectory images of the directory containing the batch file for files matching the wildcard pattern pa_10????.jpg with ignoring all other files. The found file names are output with full path and this list of file names is captured by FOR and processed line by line after WHERE finished. WHERE is executed in this case by one more cmd.exe started in background with option /c and the command line within ' as additional arguments and not by cmd.exe processing the batch file.
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 FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded where command line with using a separate command process started in background.
Each image file with full name (drive + path + name + extension) is assigned one after the other to the loop variable I. For each file name one more FOR loop is used which processes just the full path to the current image file to assign this path with a dot appended to loop variable J. The dot at end means current directory, i.e. the directory containing current image file to process.
There is next checked with the first IF condition if for that image file does not exist already a matching pa_10????_merged.jpg file in which case there is nothing to do for the current image file. That means the batch file can be executed on same folder as often as wanted because of it runs IrfanView only for the source JPEG files for which the appropriate target JPEG file does not exist already.
The second IF condition checks if the back image exists also in the directory of current front image as otherwise nothing can be merged at all.
There is next checked with the third IF condition if the target directory exists already and this directory is created if that is not the case.
The last IF condition checks once again the existence of the target directory and if that exists now as expected, IrfanView is called with the appropriate options to create the merged image file in the target directory with the appropriate file name.
The closing round bracket ) on IrfanView command line must be escaped with ^ to be interpreted literally by cmd.exe to pass this closing parenthesis to IrfanView instead of interpreting it as end of one of the command blocks opened with ( above.
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 %~dp0 ... drive and path of argument 0 which is the batch file path always ending with a backslash
echo /?
endlocal /?
for /?
if /?
md /?
setlocal /?
where /?
Double click on the text file i_options.txt in program files folder of IrfanView for the description of the IrfanView options as used in the batch file.

Renaming a computer against CSV from a batch file

We're doing a mass rename of computers at a company and while I know there is a way to do this mass rename via Powershell from a DC, there are a lot of computers that are turned off and the script will need to be run again or stragglers will need to be individually fixed.
We have a remote monitoring/management system for this company that can deploy .bat files to computers as soon as they turn on, so I figured this way would be more thorough, and also has less chance of screwing things up seeing as it's a computer renaming itself as opposed to one script renaming everything.
I came across this, and it seemed like a really good idea, but for some reason the string for "%name%" can't be found in my semicolon delimited text file.
Here's what I think the script is / should be doing:
The script finds the name of the computer that it's being run on, sets it as %oldname% variable. Then it searches the semicolon delimited text file. This file contains current names and desired new names of computers. The two names are delimited by semicolon.
So the script tries to find the previously found name, then move over to the second part of the line to find the new name (tokens2 delims=;).
Then it loads that into the newname variable, that way the wmic command can run using oldname and newname.
However, the batch file cannot find the string.
for /f %%i in ('hostname') do; set oldname=%%i
for /f "tokens=2 delims=;" %%i in ('type \\server\shared\test\names.txt ^| findstr /i "%name%"') do; set newname=%%i
wmic computername where name="%oldname%" call rename name="%newname%"
I get "Findstr: No search strings" This tells me that it cannot properly find one of the names in the text file, and I'm a bit lost. I don't know if it has to do with syntax or how the txt file is set up.
The text file is laid out as such (using three fake lines to demonstrate formatting):
Test-L7;New-3284
Kitchen-7;New-1249
MikeS-7;New-3290

Windows Batch File to count all files and subdirectories but not list

I'm need to essentially get the summary of "DIR/s" but without listing. I want to be able to see the number of files/folders/bytes used and bytes available - and pipe all that to a file?
#echo off
setlocal EnableDelayedExpansion
for /F %%a in ('dir') do (
set files=!dirs!
set dirs=%%a
)
echo %files% Files(s), %dirs% Dir(s)
Previous Batch file may be easily modified to get the number of used and available bytes, if required.
Antonio
While this can be done using command-line scripting it's FAR easier using PowerShell.
Without knowing what information you want to collect per folder and as a summary, it's not possible to provide a worked solution right now.
However, I'd encourage you to read through and experiment with the scripts and answers provided in the following threads:
A PowerShell script to find the file size and file count of a folder with millions of files?
PowerShell : how do you run a folder size summation?
powershell folder stats
HTH.

Looking for a simple Batch script that modifies file name

I have a list of files in a folder that end with .swf.
I want to change all those files from X.swf to X<some number>.swf.
How can I do that?
This little script will change all *.swf files into the equivalent *_42.swf files.
#setlocal enableextensions enabledelayedexpansion
#echo off
for /f %%a in ('dir /b *.swf') do (
set fspec=%%a
set newfspec=!fspec:~0,-4!_42.swf
echo ren !fspec! !newfspec!
)
endlocal
Actually, as it stands now, it will just echo the commands that it wants to execute. Once you're happy they're correct, you can just remove the echo from that renaming line above.
It works by using for /f to get a list of all SWF files and then using string manipulation to:
remove the last four characters (the.swf extension); then
add a new _42.swf extension onto the end.
And, please, make sure you back them up first :-)
You could use the following one-liner directly from the command prompt:
FOR %F IN (*.swf) DO RENAME "%F" "%~nF123.*"
where 123 stands for your number of choice.
Alternatively you could create a batch file and take advantage of its ability to accept parameters. Use the following script:
#ECHO OFF
SET "suffix=%~1"
FOR %%F IN (*.swf) DO RENAME "%%F" "%%~nF%suffix%.*"
Now if the batch's name is renamer.bat, you can invoke it like this:
renamer.bat 2011
and it will add 2011 to the name of every .swf file in the current directory.
Assuming <X> in your description is supposed to be constant and you don't explicitly require a batch script to solve your problem, you can use Windows Explorer as mentioned in an article by Microsoft titled "Rename a file".
Here's a an extract from said article:
"You can also rename several files at one time, which is useful for grouping related items. To do this, select the files [then press F2]. Type one name, and then each of the files will be saved with the new name and a different sequential number at the end (for example, Renamed File (2), Renamed File (3), and so on)."

Pulling portion of file and storing in a variable within a Batch File

I have a file that contains some information about the product I work on. The information I'm specifically interested in is the version of the product.
I need to read in this version and store it in a variable that I can manipulate so I can increment the version number appropriately. I'm trying to use a line like this:
for /f "tokens=2" %%i in ('type product.properties^|find "about.version=Version"') do set currentversion=%%i
I know that the file contains the string "about.version=Version" and it is immediately followed by a space and then the Version number. However when I try and echo %currentversion% there is nothing stored in it.
I'm on Windows XP, thanks.
On note: You don't need type, just give find the file name.
If you are doing above thing in a for loop, if statement or any other kind of parenthesized block in the batch file, then enable delayed expansion with
setlocal enabledelayedexpasion
earlier in the batch file first and use !currentversion! instead of %currentversion%.

Resources