using dir$ to fill an array

New to FreeBASIC? Post your questions here.
ShadowDust
Posts: 274
Joined: Oct 13, 2005 2:05
Contact:

using dir$ to fill an array

Post by ShadowDust »

i want to fill an array with all the folders in c:\ and fill another array with all the files in c:\. how?
i think this question has been answered b4, but i still dont get it lol.
hippy
Posts: 84
Joined: Nov 04, 2005 18:13
Location: UK

Post by hippy »

one way ...

Code: Select all

Option Explicit

Dim directoryArray$(1000)
Dim fileArray$(1000)

Dim directoryArrayTop&
Dim fileArrayTop&
Dim filename$
Dim i&

filename$ = DIR$("C:\*.*",16)
WHILE filename$ <> ""
  directoryArrayTop& = directoryArrayTop&+1
  directoryArray$(directoryArrayTop&) = filename$
  filename$ = DIR$
WEND

filename$ = DIR$("C:\*.*")
WHILE filename$ <> ""
  directoryArray$(0) = filename$
  i& = directoryArrayTop&
  WHILE directoryArray$(i&) <> filename$
    i& = i&-1
  WEND
  IF i& = 0 THEN
    fileArrayTop& = fileArrayTop&+1
    fileArray$(fileArrayTop&) = filename$
  END IF
  filename$ = DIR$
WEND

FOR i& = 1 TO directoryArrayTop&
  PRINT "Directory = ",directoryArray$(i&)
NEXT

FOR i& = 1 TO fileArrayTop&
  PRINT "File = ",fileArray$(i&)
NEXT
This is a bit odd to me because DIR$() returns results which are opposite to what I expected from using PowerBasic and VB, ie, I expected DIR$("C:\*.*") to not return directories, and DIR$("C:\*.*",16) to return directories plus normal files. The Wiki isn't particularly clear; The filespec can be "*" for all files/directorys, "*.*" for all files, or you can change the "*" to the file/directory name or filetype you want to search for.

And now I'm confused ....

The above code works on my PC and on most directories where there is a mix of directories and files ( ie "C:\TMP\*.*" ), but not on all ! In a couple of directories, including DIR$("C:\WINDOWS\*.*",16), it is actually returning non-directory files.

A FreeBasic bug maybe ?
tunginobi
Posts: 655
Joined: Jan 10, 2006 0:44
Contact:

Post by tunginobi »

Most people don't understand the gravity of using wildcards in their path specifiers.

"*.*" will match any file or folder that has a peroid (.) in its name.
".*" will match any file or folder with a period at the beginning of its name.
"*." will match any file or folder with a period at the end of its name.
"*" will match any file or folder, regardless of its name.

The asterisk (*) as a wildcard means "zero or more characters of any type".
ShadowDust
Posts: 274
Joined: Oct 13, 2005 2:05
Contact:

Post by ShadowDust »

tunginobi wrote:Most people don't understand the gravity of using wildcards in their path specifiers.

"*.*" will match any file or folder that has a peroid (.) in its name.
".*" will match any file or folder with a period at the beginning of its name.
"*." will match any file or folder with a period at the end of its name.
"*" will match any file or folder, regardless of its name.

The asterisk (*) as a wildcard means "zero or more characters of any type".
sh*t so in UnrealTournament it finds CTF(Capture The Flag)(or any map type) by doing this "CTF-*"

wow!!! i didnt know that thx!!
hippy
Posts: 84
Joined: Nov 04, 2005 18:13
Location: UK

Post by hippy »

tunginobi wrote:"*.*" will match any file or folder that has a peroid (.) in its name.
".*" will match any file or folder with a period at the beginning of its name.
"*." will match any file or folder with a period at the end of its name.
"*" will match any file or folder, regardless of its name."
So why does DIR$("C:\*.*",16) return only directory names such as "WINDOWS" and not the names of files such as "AUTOEXEC.BAT" which exist there, yet a DIR$("C:\WINDOWS\*.*",16) returns directory names and also some, but not all, the names of files, like "Setup1.EXE" ?

Something's not right there.

Also, if "*.*" matches files and folders which have periods, what of "C:\WINDOWS" ? Does that have a period in it ? If it does, then implicitly so does every directory name and filename. If it doesn't, then why is it returned with "*.*" ?

So what's broken ? The description of what the wildcards do, or the implementation of DIR$ which doesn't match the description ? Maybe both are wrong ?

What is the source of that interpretation as claimed by tunginobi ? That's not what it says on the FB Wiki, which is the same as in the 10-dec-2005 .CHM file ...

http://www.freebasic.net/wiki/wikka.php?wakka=KeyPgDir
Description:

Returns files/directorys in the current directory/folder. Results can be filtered with a filespec and with a matching file attribute. The filespec can be "*" for all files/directorys, "*.*" for all files, or you can change the "*" to the file/directory name or filetype you want to search for.
yetifoot
Posts: 1710
Joined: Sep 11, 2005 7:08
Location: England
Contact:

Post by yetifoot »

on windows *.* will return files named like 'COPYING' (which has no dot)
hippy
Posts: 84
Joined: Nov 04, 2005 18:13
Location: UK

Post by hippy »

yetifoot wrote:on windows *.* will return files named like 'COPYING' (which has no dot)
But is that because it's meant to do that and tunginobi's statements are wrong ( or perhaps irrelevant if refering to Linux while we're all talking about Windows ), or does it do that because DIR$ isn't working as it should ?

We need a developer who can definitively say what DIR$ is meant to do, then from that we can assess what's right or wrong, and whether DIR$ does as it should.
tunginobi
Posts: 655
Joined: Jan 10, 2006 0:44
Contact:

Post by tunginobi »

I'm stating the way that wildcards do operate. They may or may not operate that way in the DIR$ function.

It's largely because the "*.*" pattern is so ubiquitous in the realm of file management. People who didn't really understand the operation of computers would see something like "copy *.* a:" and think, "I'm copying all the files to my floppy disk!"

What they didn't realise is that "*.*" isn't necessarily equal to "all files". The stigma that it did mean that has propagated through computing, and has been incorrectly incorporated into a number of programs over the years.

Such mistakes would be unacceptable on a UNIX-based system. Try "ls *.*" on a UNIX-based shell, and indeed, all the entries must contain a period somewhere in their name. Type "dir *.*" and you indeed get a similar result.

Here's a quote from the relevant Wikipedia page:
Computing

In computer (software) technology, a wildcard character can be used to substitute for any other character or characters in a string.

The asterisk (*) usually substitutes as a wildcard character for any zero or more characters, and the question mark (?) usually substitutes as a wildcard character for any one character, as in the CP/M, DOS, Microsoft Windows and POSIX (Unix) shells. (In Unix this is referred to as glob expansion.) In SQL, the wildcard characters are percent (%) for zero or more characters, and underscore (_) for one character. In many regular expression implementations, the period (.) is the wildcard character for a single character.
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Post by coderJeff »

Dir("*.*", 16) is returning directories plus files that have no attribute set at all. This might be a bug, but, it of course depends on the expectation of Dir().

VBDOS has a Dir(spec) command that doesn't have an attrib parameter. Visual Basic has Dir(spec, attrib) that doesn't exactly do it right. You still have to use GetAttr() to really know what it is. (And if it matches the type of file/dir you are looking for)

The problem is that files that have no attributes at all (effectively a zero value) cause a problem. How do you include or exclude a zero value based on a bit mask consistently?

Dir() as it is without GetAttr() is not useable as is for some tasks and findfirstfile(), findnextfile() could be used instead. If it were up to me, I would fix Dir() by introducing an artificial attrib to indicate "is a file"

linux file systems don't have attribs the same was as dos, so most of them are simulated for use with the dir() function. I don't think there's any plans to support GetAttr().
hippy
Posts: 84
Joined: Nov 04, 2005 18:13
Location: UK

Post by hippy »

tunginobi wrote:I'm stating the way that wildcards do operate. They may or may not operate that way in the DIR$ function.
Okay, but that is in many ways irrelevant to the issue of what DIR$ does and what DIR$ is meant to do, and doesn't do much but cloud the issue at hand.

It is also not correct to say that is the "way that wildcards do operate" as if that is a universal absolute. It's the way they "usually" work ( as the Wikipedia entry acknowledges ), but by no means certain that wildcards will work that way for anything other than specific implementations.
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Post by coderJeff »

I could be wrong as I don't have a linux box to test this on but by looking at the rtl source, it would seem that: *.* and * both return "all files and folders" (igrnoring the attrib param atm) on dos/win and linux. the linux implementation of dir() checks for "*.*" and uses "*" instead. This was likely added for compatibility between dos/win and linux, and usage of *.* in existing qbasic progs.

I think the Dir() function regarding *.* is just documented incorrectly in the wiki.
hippy
Posts: 84
Joined: Nov 04, 2005 18:13
Location: UK

Post by hippy »

Thanks for that info. The primary issue for me is whether DIR$("*.*") should return (A) files only, or (B) files plus directories, and DIR$("*.*",16) should return (A) just directories, or (B) files plus directories.

DIR$("*.*",16) is returning all directories (as best I can tell ), but is also returning some but not all files. Either way it is meant to work there seems to be a bug, in returning too much or too little.
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Post by coderJeff »

If there's no GetAttr() equivalent, then I think Dir("*.*", 16) should just return directories. (So right now it's bugged) But even if that's fixed, there are still be cases where Dir("*.*", attrib) won't work right because the bitmask that's specified in attrib could be used in two ways: files matching "Any" attrib or "All" attribs.

Another idea to fix this would be a GetLastAttr() function that returns the attrib of the file/dir just returned in the last Dir() call. Seems like it should be possible based on what's already in the run-time lib's Dir() funtion. This would allow the programmer to check the attrib after the Dir() call instead of relying only on the filtering in Dir().
lillo
Site Admin
Posts: 447
Joined: May 27, 2005 8:00
Location: Rome, Italy
Contact:

Post by lillo »

What instead if we use a third optional argument to DIR? This would be a variable passed by reference, that would be filled with the attribs mask of the file returned each time DIR is called.

Code: Select all

dim as string filename
dim as integer attribs
filename = dir("*.*",,attribs)
while filename <> ""
  print "File: " & filename & " (attribs: " & attribs & ")"
  filename = dir(,,attribs)
wend
Ok, the dir(,,attribs) form is not that cool, but at least this way we avoid introducing a new keyword...
Sisophon2001
Posts: 1706
Joined: May 27, 2005 6:34
Location: Cambodia, Thailand, Lao, Ireland etc.
Contact:

Post by Sisophon2001 »

I like this idea, it looks simple and efficient, although I must admit I would be happy with any solution that works.

Garvan
Post Reply