Cheat sheet for opendir()
John Esak
john at valar.com
Tue Dec 1 05:06:23 PST 2009
>
> He has this line of code that gave me the answer:
> > ::handle_for_opendir=opendir("*.csv",foldername):
> A little bit better explanation of on this command in the
> documentation
> would help avoid this problem for people in the future.
>
> Boaz
Oh my God. I wondered how in the world you could be confused about such a
simple function, so I looked at the doc you get from within *cabe. It is
beyond horrible.
Let me clarify a couple other things. Consider this a hints list, not a
thorough doc by any means... But at least what should have been there for
you in the real doc. If you want a really, complete, thorough step-by-step
manual about opendir() or *any* filePro function.... Then check by keyword
in the Survivor Series CD's and you will be brought directly to one or more
movies that will immediately play in Windows Media Player. There is
absolutely no need to ever struggle about anything filePro with this set of
hundreds and hundreds of movies... Indexed with thousands and thousands of
keywords at your fingertips. Okay, ad over, good hints start here...
First, if you rely on the example in the code that helped you (shown above),
you may continue to be a little confused about opendir(). When you first
asked if there was a system maintained variable that holds the number of
files found by opendir() I knew that you must have misinterpreted the
docs... (Then I saw how horrid the doc on this function was ... And well...
It doesn't even state it at all clearly, so there was nothing to
misinterpret.) The syntax is this:
n=opendir(wildcard-mask,directory-path)
Now, the fellow (or gal) who wrote the code that helped you is misleading
himself or herself) the variable on the left side of the function is not a
handle. It is a "return value". It holds the number of files found by
opendir() with the wildcard-mask in that directory. So, don't think of it
as a handle but as the return value of the function itself. The more useful
list of files found by opendir() when it is encountered is thrown into a
series of system maintained arrays, @dirlist[], @dirlist_name[],
@dirlist_filename[] and @dirlist_ext[].
Here comes some of the hinty things. If you ask for *every* file in a
directory, opendir() will always find at least two (2) files. You will not
usually find n to be equal to zero even in an empty directory. That is
because there are always two files in any folder represented by "." and
"..". The dot is a file which stands for the current directory and the dot
dot is a file that stands for the parent directory. ([1] - I'll put some
very useful info at the end of the note about these.)
Assuming the name of a file is "junk.2", and it is the only file in a
directory called "/tmp/test". The program encounters
then: n=opendir("*","/tmp/test")
The variable n will be filled with "3", and those system maintained arrays
will be filled with:
@dirlist_filenam["3"] will equal "junk.2"
@dirlist_name["3"] will equal "junk"
@dirlist_ext["3"] will equal "2"
@dirlist["3"] will hold the long list of data which used to be found by
using nextdir() .... You can look nextdir() up if you want... But it is an
archaic and essentially obsolete/useless function now since the @dirlist[]
array already holds all the same data without having to retrieve it one
element at a time which is what nexdir() used to do (still does, but only
for backward compat....) If you want some of the data that is in the
@dirlist[] array, simply access it by the right element number and you can
parse out the piece you want with MID(). The nextdir() doc describes this
character by character.) Here is how it looks along the line.
@dirlist["3"] will equal "junk
2 2 12/01/2009 00:45:25a junk.2"
Look closely at the first three @dirlist_ arrays, the ones you will be using
most. Note that the @dirlist_ext does not include the ".". Note that the
@dirlist_filename value is the full filename and that the @dirlist_name
value is only the name *without* any extension. Both are useful for
different requirements.
VERY IMPORTANT NOTE
IN *all* versions of filePro, all platforms there was a bug in opendir() up
until 5.6.7 and above. It was a rare occurrence but if you had more than
1,000 files in a directory, the return value was truncated from the left to
only 3 digits. So, if you had 2913 files in a directory, the value would be
returned as 913. Even if the return_value variable has an edit big enough,
say (8,.0), it would still only be set equal to 913. My suggestion is to
get the very latest version as soon as you can... Because there are lots of
other fixes and enhancements, but in the meantime, there is a very easy
work-around. Instead of using the return value as reported by your variable
on the left side of the opendir(), just use @dirlist["0"]. It also holds
the number of files found by the opendir(), but it is not truncated and
always correct.
The search key... The wildcard... Maybe even an exact file you wish to
find....
First, a little about the wildcard_mask you will see in the filePro docs on
opendir(). FilePro will help you get all the filePro formats of a filePro
file with a few shortcuts. These are essentially factory provided
wildcards. They are:
PRC_MASK TOK_MASK SCR_MASK IDX_MASK
BRW_MASK OUT_MASK SEL_MASK
My bet is you will probably never use these. If you do however need to get
all the screens in a file or all the processing tables, etc., these are
ready made.
Be sure to put quotes around them....
n=opendir("scr_mask","test")
This will get you all the screens in the filePro file called "test" in the
current filePro directory.
IMPORTANT: The return value, nor the @dirlist arrays will contain the "."
and ".." files in this case? Why? Because you are not asking for *every*
file in the directory as was being done with "*" as the wildcard.
The same is going to be true about almost any wildcard you specify except
"*".. If you limit a search with a prefix or a suffix as in:
n=opendir("Jan.*","/tmp/fred" or n=opendir("*.Jan","/tmp/fred"
You will find files like:
Jan.120109 and 120109.jan
You are only going to retrieve files which match that criteria. The dot and
dot dot files don't ever match such a search.
You can most profitably use expressions as the search criteria.
n=opendir(aa,"/tmp/fred") or n=opendir(i_need_this,"/tmp/fred")
Which assumes that you have previously filled the dummy variable aa with
your correct search criteria, or the same with the declared variable
i_need_this.
IMPORTANT: Remember, if you want to find *every* occurrence of an expression
whether it falls at the end of a name or the beginning, you have to use the
"*" in ate appropriate place. For example:
n=opendir("*" { aa,"/tmp/fred") or n=opendir(i_need_this {
"*","/tmp/fred")
And all variations of such.
Another important thing to remember is the directory being searched is also
an expression, so it can be any kind of variable rather than a literal in
quotes.
n=opendir("*",aa)
And, of course, you have filled aa with a good directory path before this
opendir().
All right, one more really IMPORTANT hint. (the kind of thing that should be
in a doc... Not as a hint, but as a piece of information that is EXTREMELY
important.)
Boaz asked how you use opendir() on a different directory. He experimented
with chdir() and some other things I bet. It is also not very clear in the
docs, but you can only use opendir() one time... And it stays active with
all the @dirlist arrays for that particular directory... UNTIL.... You issue
a closedir() command. Then, and only then can you use opendir() again with
a different directory. You can use it as many times as you like, even in
elaborate loops in quick succession, but you MUST encounter that closedir()
before you hit the opendir line again. And, remember that opendir is a
function with a return value also... It has to be used as:
n=closedir()
You never put anything in between the parens... It just closes the last
occurrence of opendir(). And this is very important *and* useful... An
opendir() does not have to be in effect to use closedir(). It will just do
nothing and not complain if there is no previous opendir() to close.
Okay, that's enough to get you using one of the most powerful filePro
functions.
In case you want to try opendir() and do it quickly and harmlessly and
really see how cool it is in about 1 minute of code writing.... Here you go.
Usually what is done with the information opendir() gives you is this. The
return value is set as the highest number in a loop. The loop lets you step
through each file doing whatever you want with it. When you get to that
highest value, you end the loop because there are no more files to process.
But, in fact, you of course don't have to do any processing on each and
every file... You do whatever it is you need. Heck, you may want to simply
display all the files in a directory so the user can "pick" one... Then you
process that one in the way you need. This can be as simple as a pair of
lines of code. So, go pick a directory on your system and do something like
the following. Then go into the file in which you wrote this processing
with rclerk and got to record 1 and press "T".
then: end
@keyT if: '@keyT test opendir()
then: n(4,.0)=opendir("*","/tmp")
then: xx(4,.0)=listbox(@dirlist_filename,"1",n)
then: exit
FilePro is actually pretty quick and nifty at such things.
John Esak
{1} Oh yeah... I said I would tell you how to deal with the "." and the ".."
if you ever have the need. Here is a little loop that writes every filename
in a directory to an array that gets put on the screen... But it eliminates
the "." and "..".
then: dim my_array["5000"; a(4,.0)="1"; b(4,.0)="1"
then: n(4,.0)=opendir("*","/tmp"
loop if: a gt @dirlist["0"]
then: xx(4,.0)=listbox(my_array,"1",b - "1"); exit
if: @dirlist_filename[a] { "x" eq "." { "x" or
@dirlist_filename[a] { "x" eq ".." { "x"
then: a=a + "1"; goto loop
then: my_array[b]=@dirlist_filename[a]; a=a + "1"; b=b + "1";
goto loop
This simply skips the two unwanted filenames "." and ".." by incrementing
one counter (a) to move through the file list and another counter (b) when
we actually fill the array that listhbox() will show on the screen. It will
only show the correct number of names in the listbox because we are telling
it to stop at the value of b minus one. Which is the number showing how
many times we actually filled the my_array array. :-)
By the way the compare being used to test the filename against "." and ".."
makes use of the thing Nancy described a few days ago of squishing some
character against the test values so that for example, things like
".profile" and ".ssh" won't match ".". She said she uses a "~" or "|" I
think... I have always just used an "x". Any character will do, since it
does the job no matter what it is.
I hope you have fun with all this. Truly, I would never have to write
another word if people picked up the Survivor Series movies. They go step
by step from knowing NO filePro and NO programming to a point where you
could easily call yourself an EXPERT filePro programmer... But, you don't
actually have to do the step by step thing... Although I heartily suggest
it... You can just type in whatever you want at the Search index, and watch
the movies as you need them. They have always been a pretty much money back
guarantee, and I have never had anyone ask yet.
One caveat only... EVERYTHING in filePro except none of the HTML command,
ODBC or SOCKETS. Otherwise "it's in there" through ADVANCED/EXPERT level.
www.valar.com/survivor_series/choice.htm
More information about the Filepro-list
mailing list