using dir$ to fill an array
@lillo, yeah, it does look a little un-cool. ( lol, even for basic). But I think it will work, and it would certainly be much easier/faster to implement/document than a adding a new keyword.
filename = Dir([filespec [, filter [, attribs]]] )
I think an extra param should be added to Dir(). This is a good way to do it.
filename = Dir([filespec [, filter [, attribs]]] )
I think an extra param should be added to Dir(). This is a good way to do it.
Found the problem !
Create files and directory with all possible attributes ( CREATE.BAT ) ...
FreeBASIC test program (TEST.BAS) ...
Results ...
Dir$("*.*",16) doesn't return all the files nor all the directories, only those which don't have the Archive bit set, don't have the System bit set, and don't have the Hidden bit set, and don't have the Read Only bit set.
The confusion I was seeing was because some files have their Archive bits set ( most of them ), but not all.
The attrib matching code would seem at first glance to be along the lines of ...
If ( GetFileAttrib(filename$) = 0 ) Or ( ( GetFileAttrib(filename$) And attrib ) <> 0 ) Then
but that doesn't hold up to analysis, because it isn't returning those which are Hidden or Read Only. But neither is it ...
If ( GetFileAttrib(filename$) = 0 ) Or ( GetFileAttrib(filename$) = attrib ) Then
I guess it would be possible to analyse the results and determine the algorithm actually used, but it would be easier if someone could tell us :-)
Whatever the algorithm used at present, I'm not convinced it's possible to produce a list of particular types of files/directories excluding other types without a lot of work.
Code: Select all
@ECHO OFF
If "%1" == "" Goto CreateAll
MkDir C:\TESTDIR\%1.DIR
Attrib %2 %3 %4 %5 C:\TESTDIR\%1.DIR
Echo > C:\TESTDIR\%1.TXT
Attrib %2 %3 %4 %5 C:\TESTDIR\%1.TXT
Goto Exit
:CreateAll
MkDir C:\TESTDIR
Call Create ASHR +A +S +H +R
Call Create -SHR -A +S +H +R
Call Create A-HR +A -S +H +R
Call Create --HR -A -S +H +R
Call Create AS-R +A +S -H +R
Call Create -S-R -A +S -H +R
Call Create A--R +A -S -H +R
Call Create ---R -A -S -H +R
Call Create ASH- +A +S +H -R
Call Create -SH- -A +S +H -R
Call Create A-H- +A -S +H -R
Call Create --H- -A -S +H -R
Call Create AS-- +A +S -H -R
Call Create -S-- -A +S -H -R
Call Create A--- +A -S -H -R
Call Create ---- -A -S -H -R
:Exit
Code: Select all
' Use "Test -1" for Dir$("C:\TESTDIR")
' Use "Test attrib" for Dir$("C:\TESTDIR",attrib)
If Val(Command$) < 0 Then
Print
filename$ = Dir$("C:\TESTDIR\*.*")
While filename$ <> ""
Print "Dir$(""C:\TESTDIR\*.*"") = "+filename$
filename$ = Dir$
Wend
Else
If ( Val(Command$) And 1 ) <> 0 Then Print "ReadOnly ";
If ( Val(Command$) And 2 ) <> 0 Then Print "Hidden ";
If ( Val(Command$) And 4 ) <> 0 Then Print "System ";
If ( Val(Command$) And 16 ) <> 0 Then Print "Directory ";
If ( Val(Command$) And 32 ) <> 0 Then Print "Archive ";
Print
filename$ = Dir$("C:\TESTDIR\*.*",Val(Command$))
While filename$ <> ""
Print "Dir$(""C:\TESTDIR\*.*"","+Command$+") = "+filename$
filename$ = Dir$
Wend
End If
Code: Select all
C:\FreeBas>TEST 16
Directory
Dir$("C:\TESTDIR\*.*",16) = .
Dir$("C:\TESTDIR\*.*",16) = ..
Dir$("C:\TESTDIR\*.*",16) = ----.DIR
Dir$("C:\TESTDIR\*.*",16) = ----.TXT
C:\FreeBas>TEST 48
Directory Archive
Dir$("C:\TESTDIR\*.*",48) = .
Dir$("C:\TESTDIR\*.*",48) = ..
Dir$("C:\TESTDIR\*.*",48) = A---.DIR
Dir$("C:\TESTDIR\*.*",48) = A---.TXT
Dir$("C:\TESTDIR\*.*",48) = ----.DIR
Dir$("C:\TESTDIR\*.*",48) = ----.TXT
The confusion I was seeing was because some files have their Archive bits set ( most of them ), but not all.
The attrib matching code would seem at first glance to be along the lines of ...
If ( GetFileAttrib(filename$) = 0 ) Or ( ( GetFileAttrib(filename$) And attrib ) <> 0 ) Then
but that doesn't hold up to analysis, because it isn't returning those which are Hidden or Read Only. But neither is it ...
If ( GetFileAttrib(filename$) = 0 ) Or ( GetFileAttrib(filename$) = attrib ) Then
I guess it would be possible to analyse the results and determine the algorithm actually used, but it would be easier if someone could tell us :-)
Whatever the algorithm used at present, I'm not convinced it's possible to produce a list of particular types of files/directories excluding other types without a lot of work.
I don't think it's a nasty kludge; just different.
For Example:
So here's an FB version of the win32-Dir() function (slightly simplified) found in the rt-lib with an additional parameter that returns the attrib of the file. This will only run on fbc for win32. (I'd have to make different versions for dos/linux) Source lines marked with ''New show what would change to include a returned attrib parameter.
I made it in FB so users could play around with it's operation/behaviour without having to rebuild the rt-lib / compiler.
I like this idea for the dir() function.
It should also be possible to make a GetAttr(filename) function as in visual basic since win32 has GetFileAttributes() and djgpp has _dos_getfileattr(). I guess linux would have to be simulated. I just don't see an huge need for it as it is typically used with Dir(), and returning the attrib with Dir() is very efficient, and the rtl-code could be changed with little work.
@hippy, cool test program by the way. Dir() still needs to be fixed for behaviour and the test program you made certainly shows where the problems are.
For Example:
Code: Select all
'' Classic example
dim d as string
d = Dir("*.*",16)
while d > ""
print d
d = Dir()
wend
print
print
'' New form of Dir
dim retattrib as integer
d = DirEx("*.*",16,retattrib)
while d > ""
print hex(retattrib),d
d = DirEx(,,retattrib)
wend
I made it in FB so users could play around with it's operation/behaviour without having to rebuild the rt-lib / compiler.
Code: Select all
Option Explicit
#include "crt.bi"
dim shared dirhandle as integer = 0
dim shared dirattrib as integer = 0
dim shared dirinuse as integer = 0
dim shared dirdata as _finddata_t
sub close_dir
_findclose(dirhandle)
dirinuse = 0
end sub
function find_next() as string
do
if( _findnext( dirhandle, @dirdata ) ) then
close_dir( )
function = ""
exit do
end if
function = dirdata.name
loop while( dirdata.attrib and (not dirattrib ))
end function
function DirEx(strFile as string = "", byval attrib = &h33, byref retattrib as integer = 0) as string
dim ret as string
retattrib = -1 '' New
function = ""
if len(strfile) > 0 then
if dirinuse then
close_dir
end if
dirhandle = _findfirst( @strfile[0], @dirdata)
if dirhandle <> -1 then
dirattrib = attrib Or &hFFFFFF00
if ((attrib and &h10) = 0) then
dirattrib or= &h20
end if
if( dirdata.attrib and (not dirattrib )) then
ret = find_next( )
else
ret = dirdata.name
endif
if( ret > "" ) then
retattrib = dirdata.attrib '' New
dirinuse = 1
endif
endif
else
if dirinuse then
ret = find_next()
if (ret > "") then '' New
retattrib = dirdata.attrib '' New
endif '' New
end if
endif
function = ret
end function
It should also be possible to make a GetAttr(filename) function as in visual basic since win32 has GetFileAttributes() and djgpp has _dos_getfileattr(). I guess linux would have to be simulated. I just don't see an huge need for it as it is typically used with Dir(), and returning the attrib with Dir() is very efficient, and the rtl-code could be changed with little work.
@hippy, cool test program by the way. Dir() still needs to be fixed for behaviour and the test program you made certainly shows where the problems are.
-
- Posts: 1706
- Joined: May 27, 2005 6:34
- Location: Cambodia, Thailand, Lao, Ireland etc.
- Contact:
-
- Posts: 274
- Joined: Oct 13, 2005 2:05
- Contact:
i really dont have time to study this :/ how can i use it to fill an array(1 for directory's, 1 for file's).. i've been messing around with the first way.. but it just doesnt work rightOption Explicit
#include "crt.bi"
dim shared dirhandle as integer = 0
dim shared dirattrib as integer = 0
dim shared dirinuse as integer = 0
dim shared dirdata as _finddata_t
sub close_dir
_findclose(dirhandle)
dirinuse = 0
end sub
function find_next() as string
do
if( _findnext( dirhandle, @dirdata ) ) then
close_dir( )
function = ""
exit do
end if
function = dirdata.name
loop while( dirdata.attrib and (not dirattrib ))
end function
function DirEx(strFile as string = "", byval attrib = &h33, byref retattrib as integer = 0) as string
dim ret as string
retattrib = -1 '' New
function = ""
if len(strfile) > 0 then
if dirinuse then
close_dir
end if
dirhandle = _findfirst( @strfile[0], @dirdata)
if dirhandle <> -1 then
dirattrib = attrib Or &hFFFFFF00
if ((attrib and &h10) = 0) then
dirattrib or= &h20
end if
if( dirdata.attrib and (not dirattrib )) then
ret = find_next( )
else
ret = dirdata.name
endif
if( ret > "" ) then
retattrib = dirdata.attrib '' New
dirinuse = 1
endif
endif
else
if dirinuse then
ret = find_next()
if (ret > "") then '' New
retattrib = dirdata.attrib '' New
endif '' New
end if
endif
function = ret
end function
Sorry, I missed this post. Yeah, linux has a different mechanism for getting file/dir info. I just reconstructed the win32 version (because that's what I have) in FB in case anyone wanted to see how Dir works (or doesn't depending on the point of view) If Dir() function in the fb-rtlib were modified to return an attrib for Dir, it would make Dir() much more flexible and would then offer the portable solution between platforms.yetifoot wrote:Hi there CoderJeff,
i recently was trying out _findfirst etc, and found it found it wouldn't work on Linux, is there a way? i tried removing the underscore in the declaration but no joy.
Using the DirEx() function already posted here's a couple of ideas:ShadowDust wrote:i really dont have time to study this :/ how can i use it to fill an array(1 for directory's, 1 for file's).. i've been messing around with the first way.. but it just doesnt work right
Code: Select all
dim retattrib as integer, d as string, i as integer
'' get all normal dirs
d = DirEx("c:\*.*",,retattrib) '' get all dirs
while d > ""
if (retattrib and 16) <> 0 then
print "dir "; hex(retattrib),d
end if
d = DirEx(,,retattrib)
wend
'' get all normal files
d = DirEx("c:\*.*",,retattrib) '' get all files
while d > ""
if (retattrib and 16) = 0 then
print "file "; hex(retattrib),d
end if
d = DirEx(,,retattrib)
wend
Code: Select all
redim dirlist(1) as string, ndirlist as integer = 0
redim fillist(1) as string, nfillist as integer = 0
'' get all dirs/files (incl. system/hidden)
d = DirEx("c:\*.*",511,retattrib)
while d > ""
if (retattrib and 16) = 0 then '' is a file
nfillist += 1
redim preserve fillist(nfillist) as string
fillist(nfillist) = d
else
ndirlist += 1
redim preserve dirlist(ndirlist) as string
dirlist(ndirlist) = d
end if
d = DirEx(,,retattrib)
wend
for i = 1 to ndirlist
print dirlist(i)
next i
for i = 1 to nfillist
print fillist(i)
next i
-
- Posts: 274
- Joined: Oct 13, 2005 2:05
- Contact:
thanks, I appreciate it, but credit is not necessary. The code itself comes from the fb-runtime library so i guess you could credit the freebasic devs.
I just converted the code from C to freebasic and posted it so some people could play around with it. I think it would be a good idea to change the Dir() command and I will post a feature request on sf. But first I was hoping for a little discussion about it. For example, the filter attrib doesn't produce the exact same results across win32/dos/linux. hippy previously posted showing the problems with the attrib filter. What should the behaviour of the attrib param be? For me, as long as there is a way to call Dir() that gets all the files/dirs _and_ returns the attrib, I'm fine with that.
I just converted the code from C to freebasic and posted it so some people could play around with it. I think it would be a good idea to change the Dir() command and I will post a feature request on sf. But first I was hoping for a little discussion about it. For example, the filter attrib doesn't produce the exact same results across win32/dos/linux. hippy previously posted showing the problems with the attrib filter. What should the behaviour of the attrib param be? For me, as long as there is a way to call Dir() that gets all the files/dirs _and_ returns the attrib, I'm fine with that.
I recently noticed a bug report on sf about dir() and added links to this topic as a comment.Sisophon2001 wrote:Please don’t forget about this. Any solution would be great.
Adding a third parameter for dir seems like a doable and useful solution. If you don't know what I'm talking about, read the entire post.
My personal preference on Dir(spec) is that it should return all files and folders (including files with no attributes at all) and that Dir(spec, 16) should return just directories. With an extra parameter to give the actual attributes of the file (simulated for linux) additional filtering based on attrib can be done be in the user's code.
I agree with coderJeff. dir() should just flat out return files and directories, and leave the flag handling to the developer. It'd be uniform, and more importantly, it would work as people expect it to. What's the point of a function if you can't predict it's output (RND aside for a moment)?
A quick question, though: why would attribute retrieval have to be simulated for Linux?
...
Oh wait, never mind. I figured it out. FAT-type filesystems have Archive, Hidden and Read-Only attributes. Hidden files on a Linux fs are just those whose first character is the period (.), and read-only is easily obtainable by taking the file's relevant permissions (according to which user is running). I don't think there's any equivalent to Archive, but then again, who really uses it?
A quick question, though: why would attribute retrieval have to be simulated for Linux?
...
Oh wait, never mind. I figured it out. FAT-type filesystems have Archive, Hidden and Read-Only attributes. Hidden files on a Linux fs are just those whose first character is the period (.), and read-only is easily obtainable by taking the file's relevant permissions (according to which user is running). I don't think there's any equivalent to Archive, but then again, who really uses it?