List subdirectory contents with date created/modified in CMD - cmd

In short: In Windows CMD, I need to list all the contents in all of the sub-directories of a folder, and their date-created or date-modified timestamps.
In long:
I want to regularly run a command which outputs the creation datetimes of files we upload to our FTP. I'm able to do this for one folder at a time and get the output in a text file (dir . h:\uploadtimes.txt). I'd like to do this for over 100 folders in one go. Filename and datetime-created is all I need.
THANKS!

dir /? could help (or read command reference); one could use /TC switch instead of /TW one:
dir X:\folder\*.* /S /A-D /-C /TW > h:\uploadtimes.txt
Another approach giving fully qualified file names but always date-modified timestamp regardless of /T switch unfortunately:
for /F "delims=" %G in ('dir X:\folder\*.* /S /B /A-D') do #echo %G %~TG > h:\uploadtimes.txt
Resources (required reading):
(command reference) An A-Z Index of the Windows CMD command line
(additional particularities) Windows CMD Shell Command Line Syntax
(%~G etc. special page) Command Line arguments (Parameters)

Related

How to list the names of all the files and directories in a folder using for loop in a batch file

I want to list all the files and directories inside a directory using a for loop in a batch script. How can I do it?
I used below but it didn't work :
for /r %%I in (".") do ( ls -ltr '%%I') ## Listing only filenames and not directories name
Any help is appreciable.
Thanks!
If you just want a list of dirs and files, recursively, what about:
dir /b/s "."
If you want to do something special with each of the stream item, using a for loop, you could do something like:
for /f "tokens=* delims=" %%i in ('dir /b/s "."') do ( echo "%%i" )
There I used echo for echoing, but you can put whatever you need.
"to list all the files and directories inside a directory using a for loop in a batch script." you should use the DIR command.
If you open a Command Prompt window, type dir /? and press the ENTER key you should see its usage information.
One important thing to note is the /A option. What is not mentioned specifically is that using it alone, (without additional parameters D, R, H, A, S, I, L or O), enables all attributes.
Therefore to list all items in the current directory recursively in bare format you'd use:
DIR /A /B /S
or
DIR . /A /B /S
If you wanted to list them in a specific location relative to the current directory, you'd use:
DIR "Location" /A /B /S
or:
DIR ".\Location" /A /B /S
And For a specific absolute path:
DIR "L:\ocation" /A /B /S
And if you wanted it to be in the same location as the batch file itself, you can use the special variable for the current script %0:
DIR "%~dp0." /A /B /S
To perform that command within a For loop, you should first open a Command Prompt window, type for /? and press the ENTER key, to read its usage information.
You should note that you are running a command, and should therefore use a FOR /F loop, i.e.
FOR /F ["options"] %variable IN ('command') DO command [command-parameters]
But should also note that:
To use the FOR command in a batch program, specify %%variable instead of %variable.
So:
FOR /F ["options"] %%variable IN ('command') DO command [command-parameters]
As you have your command already, the options now become important. The first you need to understand is eol which whilst it seems to mean End Of Line, is specific to only one end, the beginning! What this does it does not pass any result of 'command' to the DO if it begins with a single specific character. The defualt for eol is the semicolon ;, (probably because historically it was a common line comment marker in many files). Generally, a file or directory name could include, and begin with a semicolon, so in order to include all files, you would specify a character which cannot be included in a filename, for me the simplest is ?, although I've seen many examples using |. However, when you perform a recursive DIR command, every returned line is a fully qualified path, none of which can begin with a semicolon, so you can for this task ignore eol. You clearly want everything returned, so do not require skip any lines returned. tokens and delimiters, are adjusted according to what you want to do with the results, in this case, you want the entire content of each line returned by your 'command' with no splitting on specific characters. You should note that tokens by default is 1 and delims by default is both the space and a horizontal tab characters. You should stipulate therefore that you do not want any delimiters, so that the first token is everything returned on each line of 'command'. You rarely require the usebackq option, so for the purposes of this answer, and your task, just ignore it.
Now put it all together:
FOR /F "delims=" %%G IN ('DIR "Location" /A /B /S') DO command
Finally you can use your wanted DO command with each result from your parenthesized DIR command. That result will be held within your variable %%G.
For the purposes of just viewing each result, we'll use the ECHO command, (you would just replace that with your chosen command). Please note that as each result of the DIR command is a file or directory name string, you should generally doublequote it.
allObjects.cmd
FOR /F "delims=" %%G IN ('DIR "Location" /A /B /S') DO ECHO "%%G"
Please remember to replace "Location" as needed, before running the Windows Command Script
Create two loops, one for files
for /r %%i in (*.*) do <something>
and one for directories
for /r %%i in (.) do <something>
and use the same command after do
But, since you have Cygwin installed anyway, why not use that power and do
find . | xargs -L1 ls -ltr
where find . finds all files and directories, | xargs passes the output to xargs which -L1 splits the output after each line and passes each line to ls -ltr.

Windows cmd cd into newest directory

I have a deployment directory that contains subdirectories, one for each deployment. I'm trying to write a batch script that, among other things, performs a cd into the newest one of these directories.
I know how to do this in bash (has already been ansered here as well), but I don't know how to accomplish the same thing in Windows cmd. Can anyone help me?
In a batch file following lines can be used to changed to the subdirectory with newest modification date:
#echo off
for /F "eol=| delims=" %%I in ('dir * /AD /B /O-D 2^>nul') do cd "%%I" & goto DoneCD
echo No subdirectory found in: "%CD%"
:DoneCD
The command FOR with option /F starts a new command process with %ComSpec% /c and the command line specified between ' as further arguments in background. So executed by FOR is with usual Windows installation path:
C:\Windows\System32\cmd.exe /c dir * /AD /B /O-D 2>nul
DIR executed by background command process searches with the specified arguments
in current directory
for directories because of option /AD (attribute directory)
matching the wildcard pattern * (all)
and outputs
in bare format because of option /B just the directory names without path never enclosed in "
ordered reverse by last modification date because of option /O-D and not using option /TC (creation date) or /TA (last access date) which means first the newest modified directory and last the oldest modified directory.
The output by DIR is written to handle STDOUT of the started background command process.
2>nul redirects the error message output by DIR on not finding any directory in current directory from handle STDERR to device NUL to suppress this error message.
Read the Microsoft article 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.
FOR captures everything written by DIR to handle STDOUT of started command process and processes this output line by line after started cmd.exe terminated itself.
FOR ignores empty lines which do not occur here because of DIR outputs the list of directory names without empty lines because of using /B.
FOR would split up by default a line into substrings (tokens) using normal space and horizontal tab character as delimiters. After this substring splitting is done FOR would by default check if the first substring starts with default end of line character ; in which case the line would be ignored like an empty line. Otherwise FOR would assign first space/tab delimited string to the specified loop variable I and would execute the command line with CD and GOTO.
A directory name could be for example  ;Test Folder, i.e. a directory name starting with a space and a semicolon and containing one more space. Such a directory name would be split up to ;Test (without space at beginning) and Folder and next ignored by FOR because of ;Test starts with a semicolon.
For that reason the end of line character is redefined from default semicolon to a vertical bar with eol=| which is a character no file or folder name can contain according to Microsoft documentation about Naming Files, Paths, and Namespaces. And line splitting behavior is disabled with delims= at end of options argument string after for /F which defines an empty list of delimiters. So the directory name as output by DIR is assigned to loop variable I without any modification even on being a very unusual name for a directory.
FOR executes command CD which changes current directory to the last modified subdirectory of the current directory and next command GOTO is executed to continue the processing of the batch file on the line below the label line :DoneCD. So the FOR loop execution is broken already after processing first directory name with command GOTO.
It is of course possible to use other commands after the FOR command line and the label line :DoneCD than just the ECHO line reporting that no subdirectory was found in current directory as shown by referencing dynamic environment variable CD like a command line to exit batch processing on this unusual use case or error condition case.
This FOR command line with the command GOTO to exit FOR loop after CD cannot be used in a Windows command prompt window. A solution for Windows command prompt window would be:
set "DoneCD=" & (#for /F "eol=| delims=" %I in ('dir * /AD /B /O-D 2^>nul') do #if not defined DoneCD cd "%I" & set "DoneCD=1") & set "DoneCD="
In a batch file this single line with multiple commands would be written as
#set "DoneCD=" & (#for /F "eol=| delims=" %%I in ('dir * /AD /B /O-D 2^>nul') do #if not defined DoneCD cd "%%I" & set "DoneCD=1") & set "DoneCD="
or better readable in its multi-line version with an additional echo as
#echo off
set "DoneCD="
for /F "eol=| delims=" %%I in ('dir * /AD /B /O-D 2^>nul') do (
if not defined DoneCD (
cd "%%I"
set "DoneCD=1"
)
)
if not defined DoneCD echo No subdirectory found in: "%CD%"
set "DoneCD="
First the environment variable DoneCD is deleted if it is defined by chance.
Next FOR runs cmd.exe with DIR as described above and processes the first output directory with newest modification date. The IF condition is true on newest directory as the environment variable was definitely undefined before execution of FOR. So command CD is executed to change the current directory to newest subdirectory. Then the environment variable DoneCD is defined with value 1. Any other value would be also possible like on using set "DoneCD=%%I". Important here is that for the other subdirectories output by DIR the environment variable DoneCD is now defined and so the IF condition is always false. So there is no attempt made to change in current subdirectory of initial current directory into a subdirectory not existing here or existing by chance also in the subdirectory.
Finally the environment variable DoneCD is deleted again if defined at all during execution of FOR.
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.
cd /?
dir /?
echo /?
for /?
goto /?
if /?
set /? ... explaining on last help page dynamic environment variable CD.

How to show only filenames without extensions using dir command

I'm trying to list out file names excluding their extension,
How I want it:
File1
File2
File3
How it currently is:
File1.txt
File2.txt
File3.txt
I tried using
#echo off
dir /A:-D /B
pause
but it isn't working. I tried it in both a batch file and in command prompt.
Am I using the right command?
Use FOR and ECHO to achieve this
For example, assuming the extension is always .txt:
for %f in ("*.txt") do #echo %~nf
Instead of using DIR, we are using the FOR command to go through the list and sending each one to ECHO, with the "~n" option inserted into the %f, to cause the extension to be not shown.
An alternative is
FORFILES /c "cmd /c echo #fname"
However with this I get quotation marks around each output filename, which isn't what you want.
If running inside a batch file, you need to double the %'s for variables
for %%f in ("*.txt") do #echo %%~nf
If you need to handle multiple file extensions
As long the directory doesn't contain any subdirectories whose names have an extension, you can generalise the *.txt to *.*:
for %f in ("*.*") do #echo %~nf
If you may have some filenames with only an extension
Where the file has an extension but nothing before it, e.g. .gitignore, the resulting empty ECHO command will output an inane message, such as ECHO is on. To avoid this ruining your onward plans, you can filter out lines containing ECHO is, with the FIND command and the /V option:
for %f in ("*.*") do #echo %~nf | find /v "ECHO is"
If your local language causes DOS to output something other than ECHO is then this filtering will not work. And it will miss any file that happens to contain ECHO is in the filename.
To search subdirectories too, add '/R' to the 'for'
for /R %f in ("*.png") do #echo %~nf | find /v "ECHO is"
Conclusion
This is all crazy, of course, but this is the agonising price we pay for using Batch language instead of an actual sensible language. I am like an alcoholic, promising to all and sundry that I will never write a line of Batch code again, and then finding myself coming back to do so again, sheepishly.
It'll be much easier in PowerShell
(Get-ChildItem -File).BaseName
or
Get-ChildItem | ForEach-Object { $_.BaseName }
Get-ChildItem can be replaced with the aliases ls, gci or dir and ForEach-Object can be replaced with %
So from cmd you can run either of these to achieve the purpose
powershell -Com "(ls -File).BaseName"
powershell -C (ls^ -File).BaseName
powershell (ls^ -af).BaseName
To add to Eureka's answer, the vanilla dir command cannot achieve what you're looking for.
C:\Users\jacob>dir /?
Displays a list of files and subdirectories in a directory.
DIR [drive:][path][filename] [/A[[:]attributes]] [/B] [/C] [/D] [/L] [/N]
[/O[[:]sortorder]] [/P] [/Q] [/R] [/S] [/T[[:]timefield]] [/W] [/X] [/4]
[drive:][path][filename]
Specifies drive, directory, and/or files to list.
/A Displays files with specified attributes.
attributes D Directories R Read-only files
H Hidden files A Files ready for archiving
S System files I Not content indexed files
L Reparse Points - Prefix meaning not
/B Uses bare format (no heading information or summary).
/C Display the thousand separator in file sizes. This is the
default. Use /-C to disable display of separator.
/D Same as wide but files are list sorted by column.
/L Uses lowercase.
/N New long list format where filenames are on the far right.
/O List by files in sorted order.
sortorder N By name (alphabetic) S By size (smallest first)
E By extension (alphabetic) D By date/time (oldest first)
G Group directories first - Prefix to reverse order
/P Pauses after each screenful of information.
/Q Display the owner of the file.
/R Display alternate data streams of the file.
/S Displays files in specified directory and all subdirectories.
/T Controls which time field displayed or used for sorting
timefield C Creation
A Last Access
W Last Written
/W Uses wide list format.
/X This displays the short names generated for non-8dot3 file
names. The format is that of /N with the short name inserted
before the long name. If no short name is present, blanks are
displayed in its place.
/4 Displays four-digit years
Switches may be preset in the DIRCMD environment variable. Override
preset switches by prefixing any switch with - (hyphen)--for example, /-W.
Additionally, as an alternative to the suggestion to use ("*.txt"), if your file list includes multiple extensions you might either exclude different extensions or use *.* to get all files with a . in the name. Play around with that glob to get what you want out of it.
This is possible with a dir command and a for loop:
#echo off
for /F "delims= eol=" %%A IN ('dir /A-D /B') do echo %%~nA
If you want the full path without the extension, try:
#echo off
for /F "delims= eol=" %%A IN ('dir /A-D /B') do echo %%~dpnA
For cmd one-line:
for /F "delims= eol=" %A IN ('dir /A-D /B') do echo %~nA
And for the full path without the extension, try:
for /F "delims= eol=" %A IN ('dir /A-D /B') do echo %~dpnA
These small programs, loop through all the files in the folder except directories, and echo only the filenames/full paths without the extension.
dir -Name -File
This is for PowerShell

Wildcards for directory in Windows batch command

I need to copy the contents of a folder to another folder using a batch file - the problem I'm facing is that one of the parent folders will change every day, being named after today's date. So, for example, I have the following command:
xcopy /Y /S "\\auto-jenkins\Builds\2017\R1\\[0822]\EN\\*.*" "C:\Users\Administrator\Desktop\EN"
This works fine today, unfortunately tomorrow the [0822] will not exist and the files I need will be under [0823]. Does anyone know of a way I can use a wildcard in place of [0822]?
The [08**] folder will be the only folder below \R1 if that helps...
Does anyone know of a way I can use a wildcard in place of [0822]?
You don't need a wildcard. Use the current date (in the correct format) instead. Use the following batch file.
CopyFiles.cmd:
#echo off
setlocal
rem get the date
rem use findstr to strip blank lines from wmic output
for /f "usebackq skip=1 tokens=1,2" %%g in (`wmic Path Win32_LocalTime Get Day^,Month ^| findstr /r /v "^$"`) do (
set _day=00%%g
set _month=00%%h
)
rem pad day and month with leading zeros
set _month=%_month:~-2%
set _day=%_day:~-2%
xcopy /Y /S "\auto-jenkins\Builds\2017\R1[%_month%%_day%]\EN*.*" "C:\Users\Administrator\Desktop\EN"
endlocal
Further Reading
An A-Z Index of the Windows CMD command line - An excellent reference for all things Windows cmd line related.
for /f - Loop command against the results of another command.
wmic - Windows Management Instrumentation Command.
Since there is only a single folder in the R1 directory anyway, you can use for /D to get its name:
for /D %%D in ("\\auto-jenkins\Builds\2017\R1\*") do (
xcopy /Y /S "%%~D\EN\*.*" "C:\Users\Administrator\Desktop\EN"
)
The * is a global wild-card that stands for any number of arbitrary characters. Instead of it, you could also use [????] so your folder name must consist of exactly four characters in between [].
You can use the automatic date variable %date which is country specific:
xcopy /Y /S "\auto-jenkins\Builds\2017\R1\[%date:~3,2%%date:~0,2%]\EN\*.*" "C:\Users\Administrator\Desktop\EN"
Here, the month and the day are extracted from the date string. First number is the start position (starting at 0), next number is the length.

List only path, file name and size in Windows command prompt

In Windows command prompt, I'm trying to list only path, file name and size, of all files including in a folder and its sub folders.
Like:
dir /s /b /a-d "C:\MainFolder\"
Problem is that I don't know how to show size of file. Is it possible?
From the command line:
for %F in ("c:\MainFolder\*") do #echo %~zF %F
Double up the percents if you use the command in a batch file.
Type HELP FOR or FOR /? from the command prompt for more information on the various values that are available with FOR variable expansion.
Try this command ---
for %%a in (*) do echo %%a

Resources