-
Notifications
You must be signed in to change notification settings - Fork 155
Open
Description
Ok maybe this has been suggested in the past but I thought
it might be worthwhile to possibly revisit or re-evaluate expanding
the function dir() by adding File Attributes 'size' and 'date' plus
an optional parameter to sort the output (most likely on date, name, size)
in a platform independent manner.
The following code snippets are purely to illustrate various approaches,
intended use, and considering the pitfalls they bring with them, why it
would be preferable to have freebasic's dir() have this functionality natively.
The first two are "multi platform" the third is windows specific.
example:
edir.exe na f:\dev\freebasic
sorts on name ascending
edir.exe nd f:\dev\freebasic
sorts on name descending
version using dir()
#include once "file.bi"
#include once "string.bi"
' needed for getfilesandfolders
#include once "dir.bi"
' needed for date2unixtime
#include once "crt.bi"
' setup list
type LISTBOX
as integer file ' nr of files
as integer dirs ' nr of dirs
as single tsize ' cummulated size files
as integer total ' nr items
as string item(any) ' item names
as string label(any) ' screen name item use for translations etc
as string misc(any) ' misc item use for launching apps or attributes
as string idate(any) ' item use for dates
as single isize(any) ' item use for size
end type
dim lst as LISTBOX
' used for automatic spacing columns
dim shared as integer ioffset
ioffset = 0
function date2unixtime(stamp as string, current as boolean = false) as long
dim as integer year, month, day, hour, minute, second
day = valint(mid(stamp, 1, 2))
month = valint(mid(stamp, 4, 2))
year = valint(mid(stamp, 7, 4))
hour = valint(mid(stamp, 12, 2))
minute = valint(mid(stamp, 15, 2))
second = valint(mid(stamp, 18, 2))
if current then
return time_(null)
else
return (year - 1970) * 31536000 + (month - 1) * 2592000 + (day - 1) * 86400 + hour * 3600 + minute * 60 + second
end if
end function
sub sortswap(lst as LISTBOX, i as integer, j as integer)
dim as string temp_item, temp_label, temp_misc, temp_idate
dim as single temp_isize
temp_item = lst.item(i)
lst.item(i) = lst.item(j)
lst.item(j) = temp_item
temp_label = lst.label(i)
lst.label(i) = lst.label(j)
lst.label(j) = temp_label
temp_misc = lst.misc(i)
lst.misc(i) = lst.misc(j)
lst.misc(j) = temp_misc
temp_idate = lst.idate(i)
lst.idate(i) = lst.idate(j)
lst.idate(j) = temp_idate
temp_isize = lst.isize(i)
lst.isize(i) = lst.isize(j)
lst.isize(j) = temp_isize
end sub
function sortlst(lst as LISTBOX, sortby as string) as boolean
dim as integer i, j
dim as string temp_item, temp_label, temp_misc, temp_idate
dim as single temp_isize
dim as long temp_date1, temp_date2
for i = 0 to lst.total - 1
for j = i + 1 to lst.total - 1
select case sortby
case "n"
if lst.item(j) < lst.item(i) then
sortswap(lst, i, j)
end if
case "label"
if lst.label(j) < lst.label(i) then
sortswap(lst, i, j)
end if
case "misc"
if lst.misc(j) < lst.misc(i) then
sortswap(lst, i, j)
end if
case "d"
temp_date1 = date2unixtime(lst.idate(i))
temp_date2 = date2unixtime(lst.idate(j))
if temp_date2 < temp_date1 then
sortswap(lst, i, j)
end if
case "s"
if lst.isize(j) < lst.isize(i) then
sortswap(lst, i, j)
end if
case "nd"
if lst.item(j) > lst.item(i) then
sortswap(lst, i, j)
end if
case "label"
if lst.label(j) > lst.label(i) then
sortswap(lst, i, j)
end if
case "misc"
if lst.misc(j) > lst.misc(i) then
sortswap(lst, i, j)
end if
case "dd"
temp_date1 = date2unixtime(lst.idate(i))
temp_date2 = date2unixtime(lst.idate(j))
if temp_date2 > temp_date1 then
sortswap(lst, i, j)
end if
case "sd"
if lst.isize(j) > lst.isize(i) then
sortswap(lst, i, j)
end if
end select
next j
next i
return true
end function
function getfilesandfolders(lst as listbox, path as string) as boolean
dim filename as string
Dim As Integer i, dircount, filecount
i = 0
Const attrib_mask = fbNormal Or fbHidden Or fbSystem Or fbArchive or fbReadOnly or fbDirectory
Dim As UInteger out_attr
' get folders
chdir(path)
' filename = Dir("*", fbDirectory)
filename = Dir("*", attrib_mask, out_attr)
Do Until Len(filename) = 0
redim preserve lst.item(i)
redim preserve lst.label(i)
redim preserve lst.idate(i)
redim preserve lst.misc(i)
redim preserve lst.isize(i)
lst.item(i) = trim(lcase(filename))
lst.label(i) = trim(filename)
lst.misc(i) = trim(filename)
lst.idate(i) = format(FileDateTime(filename), "dd-mm-yyyy hh:mm")
lst.isize(i) = filelen(filename)
If out_attr = fbDirectory Then
dircount += 1
else
filecount += 1
lst.tsize += lst.isize(i)
end if
' used for commandline output spacing
if len(lst.item(i)) > ioffset then
ioffset = len(lst.item(i))
end if
filename = Dir(out_attr)
i += 1
loop
lst.total = i
lst.file = filecount
lst.dirs = dircount - 2
return true
end function
' main
dim as string order, path, sort
sort = command(1)
path = command(2)
if command(1) = "/?" then
print "edir <sort> <path>"
print "sort: d, n, s equivelent of date, name, size ascending"
print "sort: dd, nd, sd equivelent of date, name, size descending"
print "example: edir.exe s c:\windows sorts on size ascending"
end
end if
if command(1) = "" then
sort = "n"
end if
if command(2) = "" then
path = exepath
end if
getfilesandfolders(lst, path)
sortlst(lst, sort)
for yy as integer = 0 to lst.total - 1
print lst.label(yy);space((ioffset + 5) - Len(lst.item(yy)));lst.idate(yy);space(20 - Len(lst.idate(yy)));lst.isize(yy)
next yy
print
Print "file(s) " & lst.file & " " & lst.tsize & " bytes"
print "folder(s) " & lst.dirs
End
version using stats, the c approach (kudos to dodicat)
#include once "file.bi"
#include once "string.bi"
#include "crt.bi"
' courtesy https://www.freebasic.net/forum/viewtopic.php?t=32809&hilit=popen dodicat
Declare Function stats Cdecl Alias "_stat"(As zstring Ptr,As Any Ptr) As Integer
dim shared as integer ioffset
dim as string dummy, locale, order, path, sort, s
sort = command(1)
path = command(2)
ioffset = 0
' setup list
type LISTBOX
as integer file ' nr of files
as integer dirs ' nr of dirs
as single tsize ' cummulated size files
as integer total ' nr items
as string item(any) ' item names
as string label(any) ' screen name item use for translations etc
as string misc(any) ' misc item use for launching apps or attributes
as string idate(any) ' item use for dates
as single isize(any) ' item use for size
end type
dim lst as LISTBOX
if command(1) = "/?" then
print "fdir <sort> <path>"
print "sort: d, n, s equivelent of date, name, size ascending"
print "sort: dd, nd, sd equivelent of date, name, size descending"
print "example: fdir.exe s c:\windows sorts on size ascending"
end
end if
if command(1) = "" then
sort = "n"
end if
if command(2) = "" then
path = exepath
end if
Function pipeout(lst as listbox, Byval s As String = "") Byref As String
Var f = Freefile
Dim As String tmp
dim as integer cnt = 0
Open Pipe s For Input As #f
s = ""
Do Until Eof(f)
Line Input #f, tmp
if len(tmp) > 2 then
redim preserve lst.item(cnt)
redim preserve lst.label(cnt)
redim preserve lst.misc(cnt)
redim preserve lst.idate(cnt)
redim preserve lst.isize(cnt)
lst.item(cnt) = trim(tmp)
lst.label(cnt) = tmp
lst.misc(cnt) = tmp
lst.idate(cnt) = tmp
lst.isize(cnt) = 1
cnt += 1
end if
s += tmp + Chr(10)
Loop
Close #f
lst.total = cnt
Return s
End Function
Function isfolder(path As zstring Ptr) As Long
#define S_ISDIR(m) (((m) And &hF000) = &h4000)
Dim As stat statbuf
If (stats(path, @statbuf) <> 0) Then Return 0
Return S_ISDIR(statbuf.st_mode)
End Function
' windows
#ifdef __FB_WIN32__
locale = ""
' issue difficult to force a date time notation ....
select case sort
case "n"
dummy = "dir /o "
case "s"
dummy = "dir /os "
case "d"
dummy = "dir /od "
case "nd"
dummy = "dir /o- "
case "sd"
dummy = "dir /o-s "
case "dd"
dummy = "dir /o-d "
case else
print "incorrect switch ... "& sort
end
end select
' unix
#else
locale = "--time-style=long-iso"
select case sort
case "n"
dummy = "ls -al "
' reverse dir /o-
'ls -al
'reverse ls -alr
case "s"
dummy = "ls -alhS "
' reverse dir /o-s
'ls -alhS
'reverse ls -alhSr
case "d"
dummy = "ls -alt "
' reverse dir /o-d
'ls -alt
'reverse ls -altr
'european ls -al --time-style=long-iso
case "nd"
dummy = "ls -alr "
' reverse dir /o-
'ls -al
'reverse ls -alr
case "sd"
dummy = "ls -alhSr "
' reverse dir /o-s
'ls -alhS
'reverse ls -alhSr
case "dd"
dummy = "ls -altr "
' reverse dir /o-d
'ls -alt
'reverse ls -altr
'european ls -al --time-style=long-iso
case else
print "incorrect switch ... "& sort
end
end select
#endif
s = pipeout(lst, dummy + locale + " " + chr$(34) + path + chr$(34))
' dir equivelent by approximation
'ls -al;df -h -T
' odd why is lst.file 1
lst.file = -1
#ifdef __FB_WIN32__
' used for commandline output spacing
for i as integer = 2 to lst.total - 3
dummy = trim(mid(lst.item(i), instrrev(lst.item(i), " ")))
if instr(lcase(lst.item(i)), "<dir>") > 0 then
lst.dirs += 1
else
lst.file += 1
lst.tsize = lst.tsize + filelen(path + "\" + dummy)
end if
if len(dummy) > ioffset then
ioffset = len(dummy)
end if
next i
' metric
'print "label ";trim(mid(lst.item(0), instrrev(lst.item(0), " ")))
'print "serial ";trim(mid(lst.item(1), instrrev(lst.item(1), " ")))
#else
#endif
for i as integer = 2 to lst.total - 3
#ifdef __FB_WIN32__
' metric windows
' if i = 0 then
' end if
' if i = 1 then
' end if
if i > 2 then
dummy = trim(mid(lst.item(i), instrrev(lst.item(i), " ")))
print dummy;space((ioffset + 5) - Len(dummy));format(FileDateTime(path + "\" + dummy), "dd-mm-yyyy hh:mm");space(5);filelen(path + "\" + dummy)
' + chr$(13) + chr$(10)
end if
#else
' metric unix
#endif
next i
print
Print "file(s) " & lst.file & " " & lst.tsize & " bytes"
print "folder(s) " & lst.dirs - 2
' metric
'print "free space ";lst.item(lst.total - 1)
'print "'";rtrim(s,chr(10));"'"
'print cbool(isfolder(rtrim(s,chr(10))))
End
version using windows api FindFirstFile and WIN32_FIND_DATA
' needed for getfilesandfolders
#include once "file.bi"
#include once "string.bi"
#include once "dir.bi"
' needed for date2unixtime
#include once "crt.bi"
#ifdef __FB_WIN32__
#Include Once "windows.bi"
#Include Once "win/shellapi.bi"
#else
#Include Once "crt/stdio.bi"
#endif
' setup list
type LISTBOX
as integer file ' nr of files
as integer dirs ' nr of dirs
as single tsize ' cummulated size files
as integer total ' nr items
as string item(any) ' item names
as string label(any) ' screen name item use for translations etc
as string misc(any) ' misc item use for launching apps or attributes
as string idate(any) ' item use for dates
as single isize(any) ' item use for size
end type
dim lst as LISTBOX
' used for automatic spacing columns
dim shared as integer ioffset
ioffset = 0
function date2unixtime(stamp as string, current as boolean = false) as long
dim as integer year, month, day, hour, minute, second
day = valint(mid(stamp, 1, 2))
month = valint(mid(stamp, 4, 2))
year = valint(mid(stamp, 7, 4))
hour = valint(mid(stamp, 12, 2))
minute = valint(mid(stamp, 15, 2))
second = valint(mid(stamp, 18, 2))
if current then
return time_(null)
else
return (year - 1970) * 31536000 + (month - 1) * 2592000 + (day - 1) * 86400 + hour * 3600 + minute * 60 + second
end if
end function
sub sortswap(lst as LISTBOX, i as integer, j as integer)
dim as string temp_item, temp_label, temp_misc, temp_idate
dim as single temp_isize
temp_item = lst.item(i)
lst.item(i) = lst.item(j)
lst.item(j) = temp_item
temp_label = lst.label(i)
lst.label(i) = lst.label(j)
lst.label(j) = temp_label
temp_misc = lst.misc(i)
lst.misc(i) = lst.misc(j)
lst.misc(j) = temp_misc
temp_idate = lst.idate(i)
lst.idate(i) = lst.idate(j)
lst.idate(j) = temp_idate
temp_isize = lst.isize(i)
lst.isize(i) = lst.isize(j)
lst.isize(j) = temp_isize
end sub
function sortlst(lst as LISTBOX, sortby as string) as boolean
dim as integer i, j
dim as string temp_item, temp_label, temp_misc, temp_idate
dim as single temp_isize
dim as long temp_date1, temp_date2
for i = 0 to lst.total - 1
for j = i + 1 to lst.total - 1
select case sortby
case "n"
if lst.item(j) < lst.item(i) then
sortswap(lst, i, j)
end if
case "label"
if lst.label(j) < lst.label(i) then
sortswap(lst, i, j)
end if
case "misc"
if lst.misc(j) < lst.misc(i) then
sortswap(lst, i, j)
end if
case "d"
temp_date1 = date2unixtime(lst.idate(i))
temp_date2 = date2unixtime(lst.idate(j))
if temp_date2 < temp_date1 then
sortswap(lst, i, j)
end if
case "s"
if lst.isize(j) < lst.isize(i) then
sortswap(lst, i, j)
end if
case "nd"
if lst.item(j) > lst.item(i) then
sortswap(lst, i, j)
end if
case "label"
if lst.label(j) > lst.label(i) then
sortswap(lst, i, j)
end if
case "misc"
if lst.misc(j) > lst.misc(i) then
sortswap(lst, i, j)
end if
case "dd"
temp_date1 = date2unixtime(lst.idate(i))
temp_date2 = date2unixtime(lst.idate(j))
if temp_date2 > temp_date1 then
sortswap(lst, i, j)
end if
case "sd"
if lst.isize(j) > lst.isize(i) then
sortswap(lst, i, j)
end if
end select
next j
next i
return true
end function
function getfilesandfolders(lst as listbox, path As String) as boolean
Dim As Integer i, dircount, filecount
i = 0
#ifdef __FB_WIN32__
Dim hFind As Long
Dim wfd As WIN32_FIND_DATA
Dim pathWithWildcard As String = path & "\*"
hFind = FindFirstFile(StrPtr(pathWithWildcard), @wfd)
If hFind <> 0 Then
Do
redim preserve lst.item(i)
redim preserve lst.label(i)
redim preserve lst.idate(i)
redim preserve lst.misc(i)
redim preserve lst.isize(i)
lst.item(i) = trim(lcase(wfd.cFileName))
lst.label(i) = trim(wfd.cFileName)
lst.idate(i) = format(FileDateTime(trim(path + "\" + wfd.cFileName)), "dd-mm-yyyy hh:mm")
lst.isize(i) = wfd.nFileSizeLow
If (wfd.dwFileAttributes And fbDirectory) Then
dircount += 1
Else
filecount += 1
lst.tsize += lst.isize(i)
End If
if len(lst.item(i)) > ioffset then
ioffset = len(lst.item(i))
end if
i += 1
Loop While FindNextFile(hFind, @wfd)
FindClose(hFind)
End If
#else
#endif
lst.total = i
lst.file = filecount
lst.dirs = dircount - 2
return true
End function
' main
dim as string path, sort, s
path = command(2)
sort = command(1)
if command(1) = "/?" then
print "dir <sort on> <path>"
print "options name, size, date"
print "example: edir.exe size c:\windows"
end
end if
if command(1) = "" then
sort = "n"
end if
if command(2) = "" then
path = exepath
end if
getfilesandfolders(lst, path)
sortlst(lst, sort)
for yy as integer = 0 to lst.total - 1
print lst.label(yy);space((ioffset + 5) - Len(lst.item(yy)));lst.idate(yy);space(20 - Len(lst.idate(yy)));lst.isize(yy)
next yy
print
Print "file(s) " & lst.file & " " & lst.tsize & " bytes"
print "folder(s) " & lst.dirs
'GetFilesAndFolders("/home/user/Documents")
End
Metadata
Metadata
Assignees
Labels
No labels