cmd.exe : both capture a folder path and parse the folder name - for-loop

In a cmd.exe batch file.
I have a directory C:\Program Files\Java containing the following directories.
\jdk-11.0.14
\jdk-17.0.2
\jdk1.8_321
I can easily parse these names using the for /f construct.
for /F "usebackq tokens=2,3,4 delims=-._" %%G in (`dir /b /a:d %ProgramFiles%\Java\jdk*"`) do (
# echo Version = %%G %%H %%I
)
Giving...
Version = 11 0 14
Version = 17 0 2
Version = 8 0 321
And, I can get the paths with...
# for /F "usebackq tokens=*" %%G in (`dir /b /a:d "%ProgramFiles%\Java\jdk*"`) do (
# echo Path = %%G
)
Path = jdk-11.0.14
Path = jdk-17.0.2
Path = jdk1.8.0_321
What I want is the path and the version information for that path together.
Specifically, I need to perform an action on the path; if the version matches some condition.

Here is an approach that seems to work.
for /D %%G in ("%ProgramFiles%\Java\jdk*") do (
echo Path = %%G
for /F "tokens=2,3,4 delims=-._" %%H in ("%%~nxG") do (
echo Version = %%H %%I %%J
)
)
Is there a better way?

Related

Why does this REN command return "The syntax of the command is incorrect"?

I have some files in a folder like:
Happysong.m4a.mp3
Sad song ft. H.E.R.m4a.mp3
I want to rename these to:
Happysong.mp3
Sad song ft. H.E.R.mp3
Here is my code for test.bat file which is placed in the same folder:
for /f "delims=" %%a in ('dir /b /a-d *.m4a.mp3') do (
set "oldName=%%~a"
set "newName=%oldName:.m4a=%"
ren %%a "%newName%"
)
It returns The syntax of the command is incorrect.
I've tried:
for /f "delims=" %%a in ('dir /b /a-d *.m4a.mp3') do (
set "oldName=%%~a"
set "newName=%oldName:.m4a=%"
ren %%a %newName%
)
which returns ft. was unexpected at this time.
What am I doing wrong here?
You could probably do it like this from cmd:
For %G In (*.m4a.mp3) Do #For %H In ("%~nG") Do #Ren "%G" "%~nH%~xG"
Or like this from a batch-file:
#For %%G In (*.m4a.mp3) Do #For %%H In ("%%~nG") Do #Ren "%%G" "%%~nH%%~xG"

Counting files and directories at each directory level from a batch file

I have successfully used a batch file which counts the total number of files and directories in a root directory.
Directory structure:
Here is the current script: (gets the number of files and folders returning subfolders up to the nth child).
#echo off
set "drive=D:\Download\app"
for /d %%r in ("%drive%\*") do (
echo Path: %%~fr
for /F "tokens=1,2,3 delims= " %%i in ('dir/a/s %%~fr ^| find /i "bytes"') do if "%%j"=="File(s)" (
set numfiles=%%i
)ELSE (
for /f %%a in ('dir /b /s /ad %%~fr ^|find /c /v "" ') do set numfolders=%%a)
echo Files: %numfiles%
echo Folds: %numfolders%
)
First the program outputs the total number of files and total number of folders in the root directory and then it goes to first subfolder and outputs the same for it's whole tree, then it moves to the next folder at that level etc.
EDIT
I have done the part where it go to 1 level of subfolders and get the total number of files and folders but I want it up to N number of subfolders which mean it should output total number for each and every folder in root directory.
Here is the extended code.
#echo off
setLocal EnableDelayedExpansion
set "drive=C:\Users\%USERNAME%\Downloads\Sandukchi"
set numfiles=
set numfolders=
set count=0;
for /d %%r in ("%drive%\*") do (
echo %%r
SET /A count=count + 1
for /d %%a in ("%%r\*") do set modifiedDate=%%~ta
for /F "tokens=1,2,3 delims= " %%i in ('dir/a/s "%%r\*" ^| find /i "File(s)"') do set fileSizeBytes=%%k
for %%* in ("%%r") do set folderName=%%~nx*
for /F "tokens=1,2,3 delims= " %%i in ('dir/a/s "%%r\*" ^| find /i "bytes"') do if "%%j"=="File(s)" (
set numfiles=%%i
)ELSE (
for /f %%a in ('dir /b /s /ad "%%r\*" ^|find /c /v "" ') do set numfolders=%%a)
echo Last Modified Date: !modifiedDate!
echo Folder Size: !fileSizeBytes! KB
echo Total Number of Files: !numfiles!
echo Total Number of Folders: !numfolders!
(
echo !count! %%r !folderName! !modifiedDate! Total Size !fileSizeBytes!KB Total Files !numfiles! Total Folder !numfolders!
echo.
)>>output.txt
)
#ECHO Off
SETLOCAL
SET "sourcedir=."
SET "tempfile=%temp%\##__##.txt"
SET "dirname="
(
FOR /f "tokens=1,2,*delims= " %%w IN (
'dir /s "%sourcedir%\*" '
) DO (
IF "%%w"=="Directory" (
SET "dirname=%sp256%%%y"&SET /a fcnt=0&SET /a dcnt=-2
) ELSE (
FOR /f "delims= " %%p IN ("%%y") DO (
IF "%%p"=="<DIR>" SET /a dcnt+=1
)
)
IF "%%x"=="File(s)" CALL ECHO %%dirname%%*%%w*%%dcnt%%
)
)>"%tempfile%"
FOR /f "tokens=1,2,*delims=*" %%a IN ('sort "%tempfile%"') DO ECHO directory %%a&ECHO files %%b&echo subdirs %%c
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
Generates a tempfile. No attempt made to delete the tempfile as it may contain useful data.
Run a standard dir/s command, and pick out the lines which start directory (which indicates a new directoryname) and those where the third space-delimited token is <DIR> for counting subdirectories. When the lines with second token File(s) appears, output the name, filecount and directorycount to a tempfile.
Sort the tempfile and report.
Note: %%y contains the third token onwards from each line. This is retokenised, selecting the first token only (default) to %%p isolating the third token of the original line.
The tempfile is produced using * as a separator since * is not a valid filename character.
dcnt is set to -2 to start the count-of-directories because both . and .. are reported as directorynames in a dir /s.
Give a try for this code :
#echo off
Setlocal EnableDelayedExpansion
#For /D %%D in (*) DO (
Set "Folder=%%~D"
PUSHD "!Folder!"
FOR /F %%H in ('dir /a-d /b 2^>NUL^|find /C /V "" ') DO ( Set "numFiles=%%H" )
FOR /F %%I in ('dir /ad /b 2^>NUL^|find /C /V "" ') DO ( Set "numSubFolders=%%I" )
POPD
echo The Folder "!Folder!" has !numSubFolders! SubFolders and !numFiles! Files
)
)
pause & exit

How to batch-copy the 10 newest files to a directory in Windows?

I use the following script to keep only the newest 360 files (a year, daily-made backup) in the directory:
for /f "skip=360 eol=: delims=" %%F in ('dir /b /o-d /a-d *.*') do #del "%%F"
How to afterwards copy the newest 7 files to another directory?
#echo off
setlocal enableextensions disabledelayedexpansion
rem Three alternatives
rem Pure arithmetics
set "numFiles=7"
for /f "delims=" %%a in ('dir /b /o-d /a-d') do (
2>nul set /a "1/numFiles", "numFiles-=!!numFiles" && (
echo copy "%%~fa" x:\somewehere
)
)
rem Pure arithmetics 2 - No negation operator
set "numFiles=7"
for /f "delims=" %%a in ('dir /b /o-d /a-d') do (
2>nul set /a "1/numFiles", "numFiles-=1" && (
echo copy "%%~fa" x:\somewehere
)
)
rem Number list of files
set "numFiles=7"
for /f "tokens=1,* delims=:" %%a in ('
dir /b /o-d /a-d
^| findstr /n "^"
') do if %%a leq %numFiles% (
echo copy "%%~fb" x:\somewehere
)

Scraping all file names with their creation and modification date from a directory

I am running this bat script, fileNames.bat > print.txt, to get all file Names.
#echo off
setlocal disableDelayedExpansion
:: Load the file path "array"
for /f "tokens=1* delims=:" %%A in ('dir /s /b^|findstr /n "^"') do (
set "file.%%A=%%B"
set "file.count=%%A"
)
:: Access the values
setlocal enableDelayedExpansion
for /l %%N in (1 1 %file.count%) do echo !file.%%N!
However, I would also like to get in the output the creation and modification date for each file path.
My current output looks like that:
C:\Programs\FirefoxPortable\fileNames.bat
C:\Programs\FirefoxPortable\Firefox
C:\Programs\FirefoxPortable\print.txt
C:\Programs\FirefoxPortable\Firefox\App
C:\Programs\FirefoxPortable\Firefox\Data
Any suggestions, how to get the creation and modification date next to each file path?
I appreciate your replies!
Following .bat script produces a csv-like output with | vertical line delimited values of next pattern:
type|creation datetime|modification datetime|full path|
Delayed expansion kept disabled as there are file names containig ! exclamation mark(s): see the call set trick in Variables: extract part of a variable (substring) and in CALLing internal commands.
Note that retrieving creation date and time discriminates between folders and files.
%%G tokenization could vary for another regional settings!
#ECHO OFF
#SETLOCAL enableextensions disableDelayedExpansion
:: Set the working directory and store the previous folder/path
pushd d:\test
:: Load the file path "array"
set "file.count=0"
for /f "tokens=1* delims=:" %%A in ('dir /s /b^|findstr /n "^"') do (
set "file.%%A=%%B"
set "file.count=%%A"
)
:: Restore path/folder most recently stored by the PUSHD command
popd
:: Access the values (keep )
set /A "ii=0"
:loop
if %ii% GEQ %file.count% goto :loopend
set /A "ii+=1"
call set "file.curr=%%file.%ii%%%"
if exist "%file.curr%\" (
rem folder
for %%g in ("%file.curr%") do (
set "defined="
for /F "skip=5 tokens=1,2" %%G in ('
dir /-c /a:d /t:C "%file.curr%"
') do (
if not defined defined (
echo FLDR^|%%G %%H^|%%~tg^|%file.curr%^|
set "defined=%%~tg %%G %%H"
)
)
)
) else (
rem file
for %%g in ("%file.curr%") do (
set "defined="
for /F "skip=5 tokens=1,2" %%G in ('
dir /-c /a:-d /t:C "%file.curr%"
') do (
if not defined defined (
echo FILE^|%%G %%H^|%%~tg^|%file.curr%^|
set "defined=%%~tg %%G %%H"
)
)
)
)
goto :loop
:loopend
ENDLOCAL
goto :eof
My current output looks as follows (reduced to reasonable size):
==>D:\bat\SO\31824138.bat
FILE|26.07.2015 11:02|26.07.2015 11:02|d:\test\File N.txt|
FLDR|24.07.2015 20:21|05.08.2015 18:44|d:\test\set|
FILE|24.07.2015 20:23|24.07.2015 20:23|d:\test\set\hklm.txt|
FILE|24.07.2015 20:26|24.07.2015 20:30|d:\test\set\regs.txt|
FILE|05.08.2015 18:44|05.08.2015 18:45|d:\test\set\t!exclam!t.txt|
==>

How to store and use the value of a batch file for loop variable

I have a Windows batch file where I'm trying to perform some operation on every file with a given name within a directory tree.
for /f "delims=" %%i in ('dir /s %1 ^| findstr /c:"Directory of"') do (
set dir=%%i
echo i = %%i
echo dir = %dir:~14%
)
My problem is that dir is always equal to the last element found in the for loop. So I may get output like this. (alignment added for clarity)
i = Directory of c:\alpha\myfile.txt
dir = c:\charlie\myfile.txt
i = Directory of c:\bravo\myfile.txt
dir = c:\charlie\myfile.txt
i = Directory of c:\charlie\myfile.txt
dir = c:\charlie\myfile.txt
So dir is never equal to "alpha" or "charlie".
What do I need to do to get the functionality I'm looking for?
Try:
for /f "delims=" %%i in ('dir /s %1 ^| findstr /c:"Directory of"') do (
set dir=%%i
echo i = %%i
call :process
)
goto :eof
:process
echo dir = %dir:~14%
goto :eof
Note that within the internal subroutine :process, %%i is not available. The call :process requires the colon and goto :eof means go to physical end-of-file (which terminates the subroutine) where the colon is required but :EOF is understood and shouldn't be assigned as a label.
Possibly better would be
for /f "delims=" %%i in ('dir /s /b %1') do (
set dir=%%i
echo i = %%i
call :process
)
goto :eof
:process
echo dir = %dir%
goto :eof
YMMV
two examples:
for /f "tokens=2*" %%a in ('dir /s ^|findstr /bc:" Directory of"') do echo %%~b
for /r %%a in (.) do echo %%~fa
This reports the path and also the full filespec.
#echo off
for /r %%a in (myfile.txt) do echo "%%~dpa" and full path is "%%a" & pause

Resources