65

I am trying to generate a text file containing the filename (including full path) and file size for all files in a particular directory and any of its sub-directories (i.e. recursively). Ideally, I don't want commas in the file size (but I'll settle for them!)

The following command does it but without the file size:

dir /b /s /a:-D > results.txt

An example output would look like:

C:\Users\Martin\Pictures\Table\original\PC120013.JPG  227298
C:\Users\Martin\Pictures\Table\original\PC120014.JPG  123234
C:\Users\Martin\Pictures\Table\original\PC120015.JPG  932344

I don't think this is possible using dir alone, although I would love to be proved wrong. Is there another way to do this, using only commands that are available from the Command Prompt?

12 Answers 12

37

This should do it:

@echo off & for /f %a in ('dir /s /b') do echo %~fa %~za

It's not very efficient...running it for folders containing a ton of files may be sketchy, so try it on small folders first.

From the "for /?" help text (I used 'a' instead of 'I')

In addition, substitution of FOR variable references has been enhanced.
You can now use the following optional syntax:

%~I         - expands %I removing any surrounding quotes (")
%~fI        - expands %I to a fully qualified path name
%~dI        - expands %I to a drive letter only
%~pI        - expands %I to a path only
%~nI        - expands %I to a file name only
%~xI        - expands %I to a file extension only
%~sI        - expanded path contains short names only
%~aI        - expands %I to file attributes of file
%~tI        - expands %I to date/time of file
%~zI        - expands %I to size of file
%~$PATH:I   - searches the directories listed in the PATH
               environment variable and expands %I to the
               fully qualified name of the first one found.
               If the environment variable name is not
               defined or the file is not found by the
               search, then this modifier expands to the
               empty string

The modifiers can be combined to get compound results:

%~dpI       - expands %I to a drive letter and path only
%~nxI       - expands %I to a file name and extension only
%~fsI       - expands %I to a full path name with short names only
%~dp$PATH:I - searches the directories listed in the PATH
               environment variable for %I and expands to the
               drive letter and path of the first one found.
%~ftzaI     - expands %I to a DIR like output line
7
  • 7
    I hit a small snag using this: files with spaces in the file name didn't register correctly. To fix this I added a "tokens=*" as follows @echo off & for /f "tokens=*" %a in ('dir /s /b') do echo %~fa %~za
    – Don Vince
    Oct 8, 2014 at 14:26
  • How to print it to a txt file? Aug 21, 2015 at 4:47
  • 3
    It should be for /r %a in (*) do echo %~fa %~za
    – ZAB
    May 11, 2016 at 20:56
  • 1
    @Saeed Neamati -- Here is an example >> C:\Temp\VideoList.txt -- The results of whatever process came before are written out to a text file named VideoList. Using one > will overwrite the file (if it already exists) and using >> will append new results onto the end if the text file (if it already exists). If the text file does not yet exist, this command writes a new file with the specified name.
    – user23715
    Jul 14, 2016 at 0:22
  • this gave me list of *.dwg files, sans the file-size, to a text file: @echo off & for /f "tokens=*" %a in ('dir *.dwg /s /b') do echo %~fa >>dwgfiles.txt
    – CAD bloke
    Feb 14, 2018 at 2:14
19

Alternative #1: FOR /R is more intuitive than #2 for me.
Alternative #2: FOR /F fixes the problem with "spaces in names" in BrianAdkins' suggestion.
Alternative #3: FORFILES would be my pick except that the path is in double quotes.

Brian or other gurus may have a more elegant solution or may be able to suggest a dozen other solutions but these three work. I tried using FOR TOKENS but then had to strip headers and footers so I reverted back to #1. I also considered creating a small .bat file and calling it but that adds another file (although it does provide greater flexibility, as would a function).

I tested all alternatives with directory and filenames with embedded spaces, a 200+ character filename, a filename with no extension, and on root of a small drive (just for time; a little slow -- just as Brian suggested -- but then so is searching in Windows Explorer; that is why I installed Everything search app).

Alternative #1: FOR /R

Best(?) While trying to figure out why Brian's solution didn't work for me I looked at HELP FOR and decided to try the /R approach. (Creating a file would be the same as in Alternative #2.)

@echo off & for /R "c:\deletelater\folder with spaces" %A in (*.*) do echo %~fA %~zA

Example - Works (different directory than above to demonstrate recursion)

@echo off & for /R "c:\deletelater" %A in (*.*) do echo %~fA %~zA
c:\DeleteLater\Name with Spaces.txt 19800676
c:\DeleteLater\NoSpacesLongName.txt 21745440
c:\DeleteLater\Folder with Spaces\2nd Name with Spaces.txt 5805492
c:\DeleteLater\Folder with Spaces\2ndNoSpacesLongName.txt 3870322
c:\DeleteLater\FolderNoSpaces\3rd Name with Spaces.txt 27874695
c:\DeleteLater\FolderNoSpaces\3rdNoSpacesLongName.txt 28726032

Alternative #2: FOR /F

BrianAdkins' suggested: @echo off & for /f %a in ('dir /s /b') do echo %~fa %~za

A corrected answer is:

@echo off & for /f "delims=*" %A in ('dir /s /b') do echo %~fA %~zA 

A more complete answer with directories suppressed and output (appended) to a file is:

@echo Results on %DATE% for %CD% >> YourDirFile.txt & echo off & for /f "delims=*" %A in ('dir /s /b /a:-d') do echo %~fA %~zA >> YourDirFile.txt

Note: "delims=*" specifies a character not allowed in filenames.
Note: 2nd command also suppresses directories via /a:-d.
Note: Made the FOR variable name uppercase to clarify the distinction between variable and variable parameters if someone chooses different variable names.
Note: Appended to file just for grins as the OP asked for output to a file.

I suppose I should really check the status of ECHO and reset it as well.

Issue - Spaces in Names

Brian's proposed solution does not handle file and folder names containing spaces (at least not on my Vista configuration).

Example - Wrong (Without delims; Includes suppressing directory per OP but with size both before and after filename for emphasis)

Truncated Name and Size (4 of 6 files incorrect):

@echo off & for /f %A in ('dir /s /b /a:-d') do echo %~zA %~fA %~zA
 C:\DeleteLater\Name
21745440 C:\DeleteLater\NoSpacesLongName.txt 21745440
 C:\DeleteLater\Folder
 C:\DeleteLater\Folder
 C:\DeleteLater\FolderNoSpaces\3rd
28726032 C:\DeleteLater\FolderNoSpaces\3rdNoSpacesLongName.txt 28726032

Example - Correct (Note output to screen, not appended to file)

@echo off & for /f "delims=*" %A in ('dir /s /b /a:-d') do echo %~fA %~zA
C:\DeleteLater\Name with Spaces.txt 19800676
C:\DeleteLater\NoSpacesLongName.txt 21745440
C:\DeleteLater\Folder with Spaces\2nd Name with Spaces.txt 5805492
C:\DeleteLater\Folder with Spaces\2ndNoSpacesLongName.txt 3870322
C:\DeleteLater\FolderNoSpaces\3rd Name with Spaces.txt 27874695
C:\DeleteLater\FolderNoSpaces\3rdNoSpacesLongName.txt 28726032

Alternative #3: FORFILES (Quote Issue)

This solution is straight from the last two examples in the FORFILES documentation (forfiles /?).

FORFILES /S /M *.doc /C "cmd /c echo @fsize"
FORFILES /M *.txt /C "cmd /c if @isdir==FALSE notepad.exe @file"

Combining these examples and writing to a file yields the answer (almost):

forfiles /s  /c "cmd /c if @isdir==FALSE echo @path @fsize" >>ForfilesOut.txt

Note that the path is in quotes in the output.
Does not matter whether echo on or echo off is toggled.
Adding a blank line separating each directory would be a trivial extension of the IF.

Caution: Using the mask /m *.* will not return files without extension (like last file in example)!

Aside: This writes a file in each directory with contents of just that directory:
forfiles /s /c "cmd /c if @isdir==FALSE echo @path @fsize >>ForfilesSubOut.txt" Not what the OP wanted but sometimes handy.

Example - Works (but with fullpath in quotes)

forfiles /s  /c "cmd /c if @isdir==FALSE echo @path @fsize"

"c:\DeleteLater\Name with Spaces.txt" 19800676
"c:\DeleteLater\NoSpacesLongName.txt" 21745440
"c:\DeleteLater\Folder with Spaces\2nd Name with Spaces.txt" 5805492
"c:\DeleteLater\Folder with Spaces\2ndNoSpacesLongName.txt" 3870322
"c:\DeleteLater\FolderNoSpaces\3rd Name with Spaces.txt" 27874695
"c:\DeleteLater\FolderNoSpaces\3rdNoSpacesLongName.txt" 28726032
"c:\DeleteLater\MoreFiles\A really really long file name that goes on and on 123456789 asdfghjkl zxcvnm qwertyuiop and still A really really long file name that goes on and on 123456789 qwertyuiop and still further roughly 225 characters by now.txt" 447
"c:\DeleteLater\MoreFiles\New Text Document no extension" 0

This example includes an extra directory with a super long filename and a filename with no extension.

Issue: Path in Quotes

So, is there an easy way to remove the unwanted(?) quotes per the OP example and save Alternative #3: FORFILES. (Rhetorical question: Are the quotes a feature or a flaw?)

3

I find the "du" command pretty helpful and it works on both Windows and Unix (used it to check if all files were copied when transferring lots of data from a Windows PC to a Linux Web Server):

du -ah "C:\your_dir" > "C:\file_list.txt"

outputs:

15  C:\your_dir/.htaccess
608 C:\your_dir/folder/hello.txt
1.0 C:\your_dir/folder/subfolder/test.txt
1.0 C:\your_dir/folder/subfolder
1.2M    C:\your_dir/folder/world.txt
1.2M    C:\your_dir/folder
9.0 C:\your_dir/no_file_ending
11  C:\your_dir/sample document 1.txt
684K    C:\your_dir/sample document 2 - äöüßÄÖÜáà.txt
1.9M    C:\your_dir

However, I could only correctly see the special characters in Notepad, not in Notepad++ (must be some ANSI/UTF-8 Encoding thing, no time to analyze exactly right now). Also I didn't find a solution to display the size after the file name. Use the "b" or "k" options instead of "h" to display size in bytes or kilobytes. I had some trouble when running the command outside the folder that I want to analyze. So best both enter the command in the right directory ("C:\your_dir" in this example) and specifying it in the command.

1
2
powershell "dir | select name,length"

This may be cheating on the OPs question. However, the question is no longer relevant on modern Windows-based systems. The Dir alias was used to help draw the logical link.

3
  • 2
    I tried this (Windows 7). It took over 30 seconds to run (on a directory with 20 entries) and it didn’t descend into subdirectories. Mar 23, 2018 at 19:25
  • 2
    To have recursion please change to: powershell "Get-ChildItem -Recurse| select name,length" Jan 7, 2019 at 11:30
  • 1
    @giorgiomugnaini How to make this work only for directories / folders, excluding the files?
    – nitinr708
    Aug 1, 2020 at 8:37
1

I realise this requires an extra utlity, but you can achieve this fairly succinctly using the sfk utility:

sfk cwd +run -yes "sfk list -size -tab $qfile +toclip"

sfk fromclip > C:\_temp\sfk_list_output.txt

(I got the approach using sfk command chaining here)

1

Below is what I used to locate misc video files that were taking up too much room on a network drive and write the results to a text file on a local PC.

I'm posting my own somewhat late answer for three reasons. One, I like concise answers. Two, this single line of script worked in multiple settings for me, including across a network. Three, per Don Vince's potentially obscure comment under BrianAdkins' answer, using tokens can bypass problems from file names with spaces in them.

for /f "tokens=*" %%a in ('dir H:\*.mov H:\*.avi H:\*.wmv H:\*.mp4 /s /b') do echo %%~fa %%~za >> C:\Temp\VideoList.txt

I noticed that very long file-paths/file-names (hundreds of characters) can also cause errors but the search won't hang on those. However the path remains not fully explored for your target(s). Once noted, you can compensate by starting deeper into the folder structure to eliminate this error.

This page ss64 has a very good presentation of the use of the dir command, listing all switches, many switch combinations, and showing several useful examples of proper syntax. It's not as comprehensive as the various Stack Exchange communities but there is a definite clarity in the presentation once you get comfortable with command line/batch scripting.

1

I have reached this with the following command:

(for /R "\path\to\directory\" %A in (*.*) do echo %~fA %~zA) | findstr /v "echo"

The result:

D:\Users\Natasha>(for /R ".\" %A in (*.*) do echo %~fA %~zA) | findstr /v "echo"


D:\Users\Natasha\Flowers_ (12).jpg 118886

D:\Users\Natasha\SomeFolder\data.txt 1241

D:\Users\Natasha\SomeFolder\CS\Counter-Strike_1.6.exe 272645624

P.S. This is based on the reply by BillR (Alternative #1). However in my case it hangs with @echo off.

1

After experimenting with "where" I found out below command works. Yes, I am searching for the answer of the OP's question.

where /T /R G:\dir1\dir2 *.*

On the other hand, below command does not work.

where /R /T G:\dir1\dir2 *.*

This output is perfect for sort and awk. If only if they can put date in YYMMDD format.

0

Simple solution for just listing files:

WHERE /R . *.*

Somebody may be able expand upon this to also include filesizes.

1
  • This answer is incomplete then. There is another WHERE answer that this should be a comment on and that answer needs a loop with delims and such to parse out the output as requested by the OP too. Jul 12, 2020 at 18:54
0

For me the best and the quickest variant for complicated folders is the combination of very quick statdart 'dir/b/b/a:-d' command and 'for /F"usebackq tokens=*"' over it's output:

for /F "usebackq tokens=*" %b in (`dir /s/b/a:-d ".\"`) do @echo %~zb %~tb %~fb
-1

Omit the b in dir /b /s /a:-D > results.txt and the results should look like, (i.e. dir /s/a: -D > results.txt):

Volume in drive H is FILES Volume Serial Number is C9EB-112E

Directory of H:\Files

09/29/2014 11:36 PM 0 testing.txt 1 File(s) 0 bytes

Directory of H:\Video\Action\Comix

10/06/2012 09:51 AM 184,740 file1.txt 07/20/2012 06:21 AM
864,832 file2.txt 08/31/2009 08:47 PM 606,638 file3.txt 08/31/2009 09:07 PM 160,320 file4.txt

1
  • This is not an answer to the original question. It does not produce the output that he OP asked for.
    – DavidPostill
    Sep 30, 2014 at 4:32
-1
where * /t  

Without getting overly complicated, this should produce the desired output. It'll give a bit more than the OP asked for, but I thought it was worth mentioning. Add the /R switch to specify a directory other than current.

4
  • 1
    Consider updating and confirming your answer works as I tried and get an error message of ERROR: Invalid syntax. Value expected for '/r' so consider going back to the drawing board and providing the correct syntax and edit your answer with the correct detail. Mar 22, 2018 at 20:27
  • Consider entering the value.../R is the directory switch, defaults to current directory if you leave it out.
    – someguy
    Mar 23, 2018 at 18:22
  • “It’ll give a bit more than the OP asked for”.  Are you kidding?  where /? says, “By default, the search is done along the current directory and in the paths specified by the PATH environment variable.” — so your where * /t command lists every file in C:\Windows\System32, some subdirectories of C:\Program Files, and every other directory in PATH.  For me, that was over 3000 lines.  Please consider editing your answer to make it reasonable. P.S. Without /R, it isn’t recursive. Mar 23, 2018 at 23:05
  • WHERE /R . *.* worked for me. /R . says to search recursively from the specified location (in this case its current directory). The *.* is the pattern to match. So WHERE /R %USERPROFILE% *.docx will show all word files in the user's folder. (Have to escape * with \ in these comments)
    – DHW
    Jul 17, 2018 at 5:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .