Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

List file names with relative path and size information

Hello

I need to list file names with relative path and size information.

dir /s /f produces almost what I need, but there is no size information and the path is full rather than starts with the subfolders of the current folder and I have to delete the beginning of the path manually.

The help file for pdir mentions /(...) option but does not give any clue where to find information of the names of the fields, etc. I found one older topic where it was suggested that one can use @name function but help file does not search for it...

thanks
 
You can get full help by looking at the TakeCommand.ewriter file but.....

pdir /s /(z @right[-3,*])

You will need to adjust -3 to suit your needs.
 
Thanks. Works perfectly.

How do I put the size after the file name ?

Where do I find that help file ? I've looked at online version Take Command / TCC Help v. 30 and still no extra details as opposed to my locally loaded file.

Why -3 in your example excludes not 3 characters (as per help file) but 3 words ? What /z means & how would I find this from the help file ??? This switch is not listed for pdir...

thanks
 
Last edited:
search that web page for

"The /(...) option specifies which fields you want to display and how to format them. (You can have multiple /(...) options on a line.) The syntax is:" and the args are discussed right below..."

pdir /s /(@right[-3,*] z)

-3 would remove the first 3 chars fro mthe file name...
 
Thanks. I now realised what you meant by "remove the first 3 chars fro mthe file name.." - you meant to delete the drive reference like "e:\" - right ?

I found TakeCommand.ewriter here: All Downloads
but it is exactly the same as online version - nothing goes after

"
PDIR command - Programmable DIR command
/(...)Use this option to define the various fields and display formats you wish to use for each selected entry. The fields may be in any order, and may be repeated. If this option is not used, the output format is identical to that of the DIR command. If you specify multiple /(...) options, PDIR will insert a space in the output between each one.

"

I've also downloaded (from the same page) pdf version of help file and searched for "s are discussed right below" - nothing found...
 
Last edited:
1686090133164.png


Joe
 
Thanks. I was looking at the very end of that help article... I've missed that that was the same option as specified in the middle of the article. Perhaps that last paragraph should be moved in front of that middle explanation.


I am still not clear on where the path information comes from ? z option produces bare file names, @right trims total output with path - right ? I've tried all f[...] options and can't produce any path (if I remove the @right function). My syntax was this:

pdir /s /(f:N z) /a-d

I'd like to doublecheck what @right function selects - characters or fileds, etc. Because when I try

pdir /s /(@right[-2,*] z) /a-d

the result is no path whereas your example

pdir /s /(@right[-3,*] z) /a-d

produces path

FInally, I found /B and /b1 switches and /b1 seems exactly what I need rather than trim first 3 characters from the full path (as I understand the @right function work). So this syntax works but I can't add size information to it

pdir /s /d /a-d /b1











 
Last edited:
Paths with the size after the file name might be ugly because the names will be of quite varying length. I don't know if this is anything like what you desire. If not, it might give you ideas. It relies on being **in** the directory of interest.

Code:
d:\tc30> pdir /a:-d /s /o:n /(z @right[%%@eval[-%%@len[%%_cwds]],%%@full[*]])
           2818 application.data
         110544 BorlndMM.dll
        8084480 DebenuPDFLibrary64DLL1411.dll
        1389328 English.dll
         913168 EnglishD.dll
         816400 EnglishE.dll
         948496 EnglishR.dll
         234256 es.exe
        1225540 Everything.chm
        2265096 Everything.exe
         [snip]
         195584 Plugins\htemp\SysUtils64.dll
        1446088 styles\Office2007.dll
        1449672 styles\Office2010.dll
        3116232 styles\Office2013.dll
        4225224 styles\Office2016.dll
          77000 styles\VisualStudio2012.dll
         158920 styles\VisualStudio2015.dll
         185544 styles\VisualStudio2017.dll
         186568 styles\VisualStudio2019.dll
         186056 styles\VisualStudio2022.dll
         517320 styles\Windows7.dll
         125640 styles\Windows10.dll
 
Paths with the size after the file name might be ugly because the names will be of quite varying length.
That's fine as I will send the list to another non-computer person who will need to check (manually on his screen) if the files are the same versions in his possession (which he can't release to me). So naturally, one searches if relevant file at all exists and then if it has the same size.

I've changed your example and it works ! Thanks
pdir /a:-d /s /o:n /(@right[%%@eval[-%%@len[%%_cwds]],%%@full[*]] z)
 
Hmmm! I tried to get the filename quoted using " or ^q or ^^q (et c.) either around @right[] or around %%@full[] and failed, getting either a quote on the end only, or an extra ^. Charles, Joe ... care to try?
 
Try moving the complexity out to a UDF:
Code:
function relname=`"%@right[%@eval[-%@len[%_cwds]],%@full[%$]]"`
pdir /a:-d /s /o:n /(@relname[*] z)
 
A smarter @RELNAME would check whether the filename really is in the current directory or below, and only truncate the filename when appropriate. But this one may be good enough for this purpose.
 
Do you mean in a format like this?

Code:
wi.bat (15)
wik.bat (15)
wiki.bat (195)
wikipedia.bat (15)
WILDCATS.BAT (84)
win-git.bat (16)
winamp-add.bat (88)
winamp-close-gracefully.bat (180)
winamp-monitor.bat (20)
winamp-playlist-randomize.bat (38)
winamp-plugins.bat (29)
winamp-randomize-playlist.bat (1,590)
winamp-stable.bat (41)
winamp-status-from-file.pl (1,016)
winamp-status-test.pl (1,474)
winamp-status.pl (985)
winamp.bat (1,424)
winamp2.bat (168)
winamp3.bat (380)
winampExe.bat (5,168)
WINDIR.BAT (12)
windows-a.ahk (26)
windowsupdate.bat (20)
wingit.bat (16)
winmx.bat (0)
WINSORT.BAT (30)
winsortclip.bat (132)

I had this need for automating making offline filelist catalogs for my burned discs.

I just do

Code:
dir /b | sizedir

Sizedir is a perl script. Which apparently got overloaded with a bunch of unrelated b.s. pertaining to my offline cataloging but regardless, it should work for you as is. I honestly forgot it did anything else but add the filesize. Wrote it 20 years ago.

I think.. if it's a rar file, it counts up the pieces and gives a summary and how many parts it is.

But yea just dir /b and pipe it to this, haha.

It also puts commas in the filesizes so they're easier to read

Code:
### OFFLINEDIR.PL.
### PURPOSE:    to easily catalog files being placed offline (ie burned cdrs, dvdrs, floppies, etc)
### USAGE:      dir /b | offlinedir <name-of-offline-media-these-files-appear-on> >>catalog_file
### EXAMPLE:     dir /b | offlinedir data-cdr-1 >>"c:\my documents\my offline files.txt"
### EXPLANATION:    takes a filelist, formats it, and adds the file's sizes (with commas) to the end of each line
### DEFINITIONS:    
#            filelist - a list of filenames, 1 per line (easily generated with dir /b)
#            format - the number of spaces the media name fits in, defined by the number in $OFFLINEFORMAT
#                    for example, if offlineformat was 15, the output of the example above would look like: "data-cdr-1    - filename (filesize)". notice how from the d in "data" to the "-" it is 15 characters
#            | - used to pipe the output of dir /b into this script
#            >> - used to append this output to the catalog file.  Note that using > would overwrite the file, so keep daily backups!




my $OFFLINEFORMAT="%-17s";
####################^^^^ this is how offline.txt is set up -- it is X characters before the " - episode/filename" is written...
####################A sample line would look like:
####################data-dvdr-95      - PlayStation2 Network Disk Backup.nrg (143,133,421)





####################################################################################
use strict;
my $line, my $date, my $time, my $fileSize, my $fileName, my $LAST_WAS_MULTIPART;
my $tally_filename, my $tally, my $fileSizeUgly, my $output, my $part_number;
my $parts_tallied=0, my $IS_ARCHIVED_VIDEO=0, my $last_part_number = -1;
my @LINES=();

##### Get disc-number from command-line arguments or current path:
my $OfflineMediaEntityName = $ARGV[0];
#my $curdir = Win32::GetCwd();
#if ($curdir =~ /(video-dvdr-[0-9]+)/) {
#    $OfflineMediaEntityName=$1;
#    $IS_ARCHIVED_VIDEO=1;
#}

#use File::Find;
#&find({wanted=>\&wanted, no_chdir=>1},$curdir);


##### Format the left (disc) side of the offline listin:
my $leftside=sprintf($OFFLINEFORMAT,$OfflineMediaEntityName) . " - ";

##### For each file:
while ($line=<STDIN>) {    push(@LINES,$line); }

#### FORK: offlinedir.pl: IF NO LINES PASSED, JUST GET EACH FILE FROM THE DIRECTORY.


foreach $line (@LINES) {
    chomp $line;  $line =~ s/^\s+//g;  $line =~ s/\s+$//g;    $output="";
    if ($line =~ /[0-9]\/[0-9]+\/[0-9]+/) {
        ($date,$time,$fileSize,$fileName)=split(/\s+/,"$line",4);
        $output .= "$fileName ($fileSize)\n";
    } else {
        $fileName=$line;
        if (!-e $fileName) {
            $output .= $line . "\n";
        } else {
            $fileSizeUgly = -s $fileName;
            $fileSize     = &commaize($fileSizeUgly);
            if (-d $fileName) {
                $fileSize="directory"; next;        #If it's a directory, say nothing & start loop over.
            }#endif
            if (($OfflineMediaEntityName ne "") || ($OfflineMediaEntityName eq "/v")) {
                $output = $leftside;
            }#endif
            #print "$fileName ($fileSize)\n";
            #if it's a multipart file, it's extremely convenient to print a total
            if (($fileName =~ /part([0-9]+)/i) && ($fileName =~ /[rza][aic][rpe]$/i)) {        
                $fileName =~ /part([0-9]+)/i;
                $part_number    = $1;
                #goat
                if ($part_number < $last_part_number) {
                    #print the summary, but no point if it's only 1 part (probably a multipart split across multidiscs)
                    if ($parts_tallied > 1) {
                        $output .= "$tally_filename ($parts_tallied parts:".&commaize($tally).") \n$leftside";
                    }
                    $tally=0; $parts_tallied=0;
                    $LAST_WAS_MULTIPART=0;        #variablename not quite right.. GOAT
                } elsif ($LAST_WAS_MULTIPART==0) {
                    $LAST_WAS_MULTIPART=1;
                }
                #DEBUG:print "parts_tallied was $parts_tallied\n";
                $parts_tallied += 1; 
                #DEBUG:$output .= "$part_number < $last_part_number\n\t\t    ";
                $last_part_number = $part_number;
                $tally_filename = $fileName;
                $tally_filename =~ s/part([0-9])+//i;
                $tally_filename =~ s/\.\././i;
                $tally += $fileSizeUgly;
                $output .= "$fileName ($fileSize)\n";
            } elsif ($LAST_WAS_MULTIPART==1) { 
                if ($parts_tallied > 1) {
                    $output .= "$tally_filename ($parts_tallied parts:".&commaize($tally).")\n$leftside";
                }
                $output .= "$fileName ($fileSize)\n";
                $LAST_WAS_MULTIPART=0; $part_number=""; $tally=0; $parts_tallied=0;
            } else {
                $last_part_number = -1;
                $output .= "$fileName ($fileSize)\n";
            }#endif
        }#endif
    }#endif
    print $output;
}#endwhile
#DEBUG:print "$part_number < $last_part_number\n\t\t    ";
if (($last_part_number > 0) && ($parts_tallied > 1)) {
    print $leftside . "$tally_filename ($parts_tallied parts:".&commaize($tally).")\n";
}
####################################################################################

#############################################
sub commaize {
    my $s = $_[0];
    while ($s =~ /[0-9]{4}/) {
        $s =~ s/([0-9])([0-9]{3})$/$1,$2/g;
        $s =~ s/([0-9])([0-9]{3}),/$1,$2/g;
    }#endwhile
    return($s);
}#endsub comma
#############################################
########################################################################
#sub wanted {
#    my $name = $File::Find::name;
#    print "$name\n";
#}#endsub wanted
########################################################################
 
This is getting bizarre, but it does quote the filename when it needs to be quoted.
Code:
v:\> d "a b"
2023-06-07  12:45               0  a b

v:\> pdir /a:-d /s /o:n /(@quote[%%@right[%%@eval[-%%@len[%%_cwds]],%%@full[%%@unquote[*]]]] z)   | head /n4
3xplus1.btm             442
1016.btm             141
"a b"               0
age2dhms.btm             443

I think * (inside a function) is automatically quoted if needed and that screws up the @right.
 
Ya know ... struggling with PDIR is fun, as long as it's done seldom.

@Charles Dye's suggestion (move the complexity) was a good one, in this case, to a script. A script is much easier to do anything with (including writing it in the first place).

Code:
:: REPORT.BTM
:: Syntax: REPORT.BTM ["]drive:\directory["]

cdd %1

:: DO /S changes the current directory (like GLOBAL)
:: so get this length now
set ntrim=%@len[%_cwds]

do f in /s *
    set fullname=%@full[%f]
    set size=%@filesize["%fullname"]
    set trimname=%@right[-%ntrim,%fullname]
    set qtrimname=%@quote[%trimname]
    echo %qtrimname^t%size
enddo

cdd -
 

Similar threads

Back
Top