I am trying to make a custom directory listing in batch using for
loops.
This is the code:
for /F "tokens=* UseBackQ" %%g IN (`dir /b %2`) do (
echo ^| %%~ag %%~tg %%~zg %%~nxg && echo ^|
)
The output with %2
being E:\
is:
| d---------- 2022-08-19 02:14 PM 0 AppTemp
|
| --a-------- 2022-08-06 11:40 PM 971 learned.py
|
| --a-------- 2022-08-19 05:00 PM 4269 main.cmd
|
I would like the file size to be like this:
| d---------- 2022-08-19 02:14 PM 0 AppTemp
|
| --a-------- 2022-08-06 11:40 PM 971 learned.py
|
| --a-------- 2022-08-19 05:00 PM 4269 main.cmd
|
How can I make it like this?
There could be used the following a little bit commented batch file code:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Make the directory passed as second argument the current directory
rem checking if a second, non-empty argument string is passed at all to
rem the batch file and with checking if that is really a directory name.
set "RestoreCurrentDirectory="
if "%~2" == "" (
echo No directory specified as second argument, listing the directory:
echo "%CD%"
echo(
) else pushd "%~2" && set "RestoreCurrentDirectory=1" || (
echo "%~2" is not a valid directory.
echo(
exit /B 1
)
rem Get the file size of the largest file in the current directory
rem assigned to environment variable with the name LeadingSpaces.
set "LeadingSpaces="
for /F "eol=| delims=" %%I in ('dir /A-D /B /O-S 2^>nul') do (
set "LeadingSpaces=%%~zI"
if defined LeadingSpaces goto GetSpaces
)
set "LeadingSpaces= "
set "NumberSpaces=1"
goto OutputFileNames
rem Replace all digits in file size of largest file by spaces. The string
rem value of the environment variable LeadingSpaces has exactly the same
rem number of spaces as the file size of the largest file in the current
rem directory has as string. Next determine the number of spaces using code
rem from https://www.dostips.com/DtTipsStringOperations.php#Function.strLen
:GetSpaces
setlocal EnableDelayedExpansion
for %%I in (0 1 2 3 4 5 6 7 8 9) do set "LeadingSpaces=!LeadingSpaces:%%I= !"
set "TempString=#%LeadingSpaces%"
set "NumberSpaces=0"
for /L %%I in (12,-1,0) do (
set /A "NumberSpaces|=1<<%%I"
for %%J in (!NumberSpaces!) do if "!TempString:~%%J,1!" == "" set /A "NumberSpaces&=~1<<%%I"
)
endlocal & set "LeadingSpaces=%LeadingSpaces%" & set "NumberSpaces=%NumberSpaces%"
rem List all files in the specified directory with right aligned file size
rem with the definition of environment variable FileSize with the leading
rem spaces on which the real file size is appended and output only the last
rem NumberSpaces characters of the file size string with spaces at beginning.
:OutputFileNames
for /F "eol=| delims=" %%I in ('dir /A-D /B 2^>nul') do (
set "Attributes= | %%~aI"
set "FileTime=%%~tI"
set "FileSize=%LeadingSpaces%%%~zI"
set "FileName=%%~nxI"
setlocal EnableDelayedExpansion
echo !Attributes! !FileTime! !FileSize:~-%NumberSpaces%! !FileName!& echo ^|
endlocal
)
if defined RestoreCurrentDirectory popd
endlocal
ATTENTION:
The Windows Command Processor cmd.exe
fails to get the file attributes with %%~aI
, the last modification time with %%~tI
and the file size with %%~zI
of a file with sharing access denied completely in comparison to command DIR of cmd.exe
which gets the data directly from the file system.
If this batch file is called with second argument being %SystemDrive%\
and the root directory of the system drive contains only the two files hiberfil.sys
and pagefile.sys
, the output of the batch file is:
| hiberfil.sys
|
| pagefile.sys
|
The file attributes hidden and system of hiberfil.sys
and pagefile.sys
do not matter. The sharing violation is the cause of not getting all the data of these two files for the output.
It would be perhaps better to run DIR and parse its output, but the date/time format of the output of DIR depends on region/country configured for the current user account which makes it most likely not possible to code the batch file for working on all Windows computers.
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
dir /?
echo /?
endlocal /?
exit /?
for /?
if /?
popd /?
pushd /?
rem /?
set /?
setlocal /?
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 dir
command line with using a separate command process started in background.
See also single line with multiple commands using Windows batch file for an explanation of the unconditional command operator &
and the conditional command operators &&
and ||
.