Guidance
指路人
g.yi.org
Guidance Forums / Rapid-Q Basic / dir /s function in qbasic

Register 
注册
Search 搜索
首页 
Home Home
Software
Upload

  
Forum List • Thread List • Reply • Refresh • New Topic • Search • Previous • Next First 1 Last
Message1. dir /s function in qbasic
#535
Posted by: 2002-10-11 16:41:23
anyone out there that can give me pointers to where i can get a function to read all files and dirs under a given root dir like dir/s?

(QDIR doez not work.. the 'dirs' function is not working)..

/thanx
Message2. qdir works very well in my pc
#536
Posted by: guidance 2002-10-11 19:54:29 Last edited by: guidance 2010-11-21 20:36:10 (Total edited 1 time)


click the icon to download.

don't know why yours doesn't, could you show us more detail?
Message3. Re: qdir works very well in my pc
#537
Posted by: 2002-10-11 20:37:11
Thanx for answering.. this is what I get..

This is the code: taken strait out of the qdir.txt

$INCLUDE "qdir.Inc"
DECLARE SUB OnFileFound_ShowFileParams
Dim myDir As QDir
myDir.OnFileFound = OnFileFound_ShowFileParams
myDir.Dirs ("c:/WINNT/*.txt", "D", "A")
Print "path = ";myDir.path
Print "IS QDIR WORKING?"
Sleep 1000
End
Sub OnFileFound_ShowFileParams
Print myDir.path & myDir.FileName
End sub

The result i get is this:

c:\\WINNTActive Setup Log.txt
c:\\WINNTcard3d.txt
c:\\WINNTEnvChecklog.txt
c:\\WINNTModemDet.txt
c:\\WINNTModemLog_Lucent Win Modem.txt
c:\\WINNTModemLog_Standard Modem over IR link.txt
c:\\WINNTModemLog_Xircom MPCI+ Modem 56 WinGlobal.txt
c:\\WINNTntbtlog.txt
c:\\WINNTOEWABLog.txt
c:\\WINNTSchedLgU.Txt
c:\\WINNTsetuplog.txt
path = c:
IS QDIR WORKING?

The problems i see is that the path for each hit is wrong (c:\\). Then only a fraction of files are listed.

Then this is the result after running WINNT>dir *.txt /s

.
..
.
.
.
.
.
.
.
     Total Files Listed:
            1554 File(s)      9?049?811 bytes

The dir command found 1554 files.

Talk to you later.

(BTW I'm running a win2000 machine)..

/A
Message4. I tried example 2, works well.
#538
Posted by: guidance 2002-10-11 22:06:42
In QdirTest.bas. I run win2000 also.
Message5. Re: I tried example 2, works well.
#539
Posted by: 2002-10-11 22:29:10
Hi,

So if you copy the program from my previous post what is ure result then?

Try your winnt dir..

Could you please copy some lines of tha printout in ure answer? and tell me how many *.txt files u found. (I know it will differ but you will have around 1000 - 2000 text files in ure installed winnt dir.)

Tanx.

/A
Message6. Problem reproduced!
#540
Posted by: guidance 2002-10-11 23:09:46
Seems QDir need to be debugged ...
Message7. Re: Problem reproduced!
#541
Posted by: 2002-10-12 04:08:47
Perfect!..

Do you have contact with the creator of QDIR?... else I'll send an email..

Tanx for checking!

/A
Message8. Re: Problem reproduced!
#542
Posted by: 2002-10-12 04:22:40
BTW...
I made a post in this forum
http://rapidqworld.proboards12.com/index.cgi?board=General&action=display&num=1034324306

Where I'm showin' code to do the same thing as QDIR... but the godda&mn program is crashing on me!... that would be a workaround insted of using QDIR (whatever.dirs)... but when I try to realize that in code the rapidq exe just crashes..... any ideas about that?....... .
There must be a way of showing dirs under a given root dir... if not I'll just have to use some other language.

Tnx again...

/A
Message9. Analysis
#543
Posted by: guidance 2002-10-12 07:29:11
No, I didn't contact the qdir author.

This is a "Frequently Taken Mistake" about dir$ or findfirst/findnext API call usage in recurse.
Because this function pair is non-reentrance, i.e., once we call findfirst(same with the first call of dir$) , the OS will save the environment for the following findnext(same with dir$ without parameter), but this is only one instance, we can not change to another directory and call another findfirst then jump back during that, if you jump back, the next findnext will continue with this new environment, unless you call the original findfirst again! But once you call the original findfirst again, the scan will restart from beginning, not resume from the last finding.

Let's look at the key code of QDir.inc (line number added):
-------------------------------------------
SUB Dirs2 (sPathFilter AS STRING, sRejectedAttributes AS STRING, sMustAttributes AS STRING)
       DEFSTR pathFilter, sFileFound, sNewPathFilter, bckPath, bckFilter
       DEFSTR bckRejectedAttributes, bckMustAttributes, bckFilter_2
       DEFINT bckHSearch
       IF .OnFileFound THEN
                'Get The Files Only
                '------------------
        IF INSTR(sRejectedAttributes, "D") = 0 THEN
         .rejectedAttributes = sRejectedAttributes & "D"
        ELSE
         .rejectedAttributes = sRejectedAttributes
        END IF
        IF INSTR(sMustAttributes, "D") THEN
         .mustAttributes = sMustAttributes - "D"
        ELSE
         .mustAttributes = sMustAttributes
        END IF
        pathFilter = REPLACESUBSTR$(sPathFilter, "/", "\\")
        sFileFound = .GetFirstFile (pathFilter)
        WHILE sFileFound <> ""
         CALLFUNC .OnFileFound
         sFileFound = .GetNextFile
        WEND
        bckFilter_2 = .Filter
                ' Get The Directories
                ' -------------------
        .rejectedAttributes = "AHNRSTC0"  ' Reject All Except Dir
        sFileFound = .GetFirstFile (LEFT$(pathFilter, RInstr(pathFilter, "\\")) & "*")
1       WHILE sFileFound <> ""
         IF INSTR(sRejectedAttributes, "D") = 0 THEN CALLFUNC .OnFileFound
         IF (.FileName <> "." AND .fileName <> "..") THEN
          sNewPathFilter = .path & .fileName & "\\" & bckfilter_2
          bckPath = .path      ' Saved Before Recursive Call
          bckFilter = .filter
          bckHSearch = .hSearch
          bckRejectedAttributes = .rejectedAttributes
          bckMustAttributes = .mustAttributes
          .rejectedAttributes = sRejectedAttributes ' The ones received by the Dirs2
          .mustAttributes = sMustAttributes
                        ' ------  RECURSIVE CALL ------------------
2         .Dirs2 (sNewPathFilter, .rejectedAttributes, .mustAttributes)
                        ' ------  RECURSIVE CALL ------------------
          .mustAttributes = bckMustAttributes
          .rejectedAttributes = bckRejectedAttributes
          .path = bckPath      ' reload after recursive call
          .filter = bckFilter
          .hSearch = bckHsearch
         END IF
         sFileFound = .GetNextFile
        WEND
       ELSE
        SHOWMESSAGE ("Event QDir.OnFileFound  Not Defined")
       END IF
      END SUB

-----------------------------------------
The algorithm is clear:
Scan the files first, then directories, for every directory it found, call itself again, recursively (line 2).

In fact, once dirs2 is recursed, we can't resume to the scan where we left any more, the environment is changed (to the subdirectory in this case). Since this problem is due to the win32 api service feature, obviously will happen in any other languages.

Solution:
Never leave the scan and call another findfirst in middle, no matter recursively or not. Instead, save all scanned output till no more files/subdirectories found, in one simple loop.

You can search the web, there're many VB code for this purpose, they're easy to convert to RQ.

Checked your code, also has this problem. By the way, suggest don't change the current directory, use full path instead while call dir$ to keep the code clean. Anymay, up to you.

Guidance
Message10. Re: Analysis
#544
Posted by: 2002-10-12 17:39:47
Hey.. thanx for spending ure time on this matter..

I'll kick back during the weekend... a coupple of beers in the sauna usually get the cells working... and then I'll try to produce working code next week...


/A
Message11. OK I'm back...
#545
Posted by: 2002-10-14 03:21:26
Hi there...

Now when my hangover is getting better I spent some time making code to preform what DIR /S is doing...

And here it is:

' WORKING DIR /S for rapidQ
$include "rapidq.inc"

dim filelist$(6000) ' u should probably write something like "as string" but I notice no difference when not declaring datatype...
dim filelist_attr(6000) as byte

Get_all_files:

    ' init

    maxnofiles=6000
    for a=0 to maxnofiles
    filelist_attr(a)=0
    filelist$(a)=""
    next a
    currfilepek=0
    workingdir=0

    ' end init

    ' do this to init a dir /s session

    filelist$(currfilepek)="C:tst" 'root dir
    filelist_attr(currfilepek)=16
    currfilepek=currfilepek+1
    gosub get_dir_struct
   
    ' the filelist now contains the dir struct
    ' u can do something like this :
   
    'tmp=currfilepek   
    'gosub get_dir_struct
    'here temp points at the dir struct start
    'temp=currfilepek-temp   and this is the length of the struct..
    'with this info u can move things around and do more crap...

cpuhog:
    goto cpuhog
   
get_dir_struct:
    while workingdir < currfilepek
        if filelist_attr(workingdir) = 16 then
            print "(main call) getting dir: "+filelist$(workingdir)
            gosub get_dir
        end if
     workingdir=workingdir+1
    wend
   
    'debug

    print "im done"
    print currfilepek
    print workingdir
   
    'end debug
   
return
   

get_dir:

    currentread$=DIR$(filelist$(workingdir)+"*.*",faDirectory )
 
    while currentread$<>""
        if currentread$="." or currentread$=".." then
            goto skipread
        end if
        filelist_attr(currfilepek)=FileRec.attr AND 16
        if filelist_attr(currfilepek)=16 then
            currentread$=currentread$+""
        end if
        filelist$(currfilepek)=filelist$(workingdir)+currentread$
        'debug
        print filerec.attr
        print filelist$(currfilepek)
        print currfilepek
        print filelist$(workingdir)+"*.*"
        'end debug
        currfilepek=currfilepek+1 
        if currfilepek=6001 then
        goto cpuhog 'do something fun here like crash the computer or format c: (hehe)...
        end if
skipread:   
        currentread$=DIR$
    wend

    return


Once again thanx for explaining how DIR$ worked!..

AN COOL / TCB
Message12. Suggestion
#546
Posted by: guidance 2002-10-14 09:39:16
Glad to see you solved problem by yourself!
There're several suggestions to exert the power of Rapid-Q:

1) use QStringList instead of array of string.
2) use sub/function instead of gosub/return.
3) use inc(var,1) or var++ instead of var=var+1

may more ...
Message13. Re: dir /s function in qbasic
#581
Posted by: 2002-10-21 18:47:53

French saying : "Better ask God than it's Saints"

Here is God reply :

It looks like that   QDIRS requires    $ESCAPECHAR ON    :)

Examples are following

Jacques
Message14. Re: dir /s function Correction Examples
#582
Posted by: 2002-10-21 19:13:13

$ESCAPECHARS ON in only required When DIM myDIR As QDir

$ESCAPECHARS ON
    Dim myDir As QDir
$ESCAPECHARS OFF

There must be then a PATH problem in Object Constructor
 ... minor bug !

Jacques

' ------- CODE TEST  -------- Should work
$INCLUDE "qdir.Inc"

DECLARE SUB OnFileFound_ShowFileParams

DefInt iFoundFilesCounter = 0

' $ESCAPECHARS ON only needed here >>> PATH in CONSTRUCTOR to BE CHECKED
$ESCAPECHARS ON
    Dim myDir As QDir
$ESCAPECHARS OFF

myDir.OnFileFound = OnFileFound_ShowFileParams

'Choose one of the two following lines (change "Windows" to "WINNT" for WinNt :)
'-------------------------------------
myDir.Dirs ("c:/Windows/*.txt", "D", "")        ' N0 MUST AERGUMENTS REQUIRED
'myDir.Dirs ("c:Windows*.txt", "D", "")        ' N0 MUST AERGUMENTS REQUIRED

Print "path = ";myDir.path
Print "IS QDIR WORKING? "

' EXIT CONSOLE
' ------------
DefStr sExit
Input "nn                    CR to QUIT nn", sExit
Application.Terminate
End

Sub OnFileFound_ShowFileParams
    DefStr sTmp
    Inc iFindFilesCounter
    sTmp = Str$(iFindFilesCounter) & " " & myDir.path & myDir.FileName
    Print sTmp
End sub
' ----------- END CODE TEST -----------------
Message15. Still same problem :(
#584
Posted by: guidance 2002-10-21 20:15:44
I tried above example, just the same problem as before: only the files in the root directory are listed, plus one file in a sub-sub-directory.

Don't you agree my analysis for the improper usage of findfirst/findnext ?
Message16. Re: Still same problem :(
#585
Posted by: 2002-10-21 23:10:46

It works here under WIN98 !

QDir.Dirs only listed the Root directory files here too without the
$ESCAPECHARS ON/OFF correction ?

I spent a lot of time on that recursive loop :) ! Not easy to get in it !
I used QDir in few codes and it works, so your analysis must be wrong :)

It could be :
- A problem in Path due to $ESCAPECHARS ?
- Or a specific NT problem ? There is a note about MAX_PATH and WINNT in
  FindFiles API ??? But I dont think it's that ???
- Did you wait long enough after QDIR found the files in your root
  directory ? QDir is Slow ? While scanning in c:/Windows here, there is a
  ?? 10 seconds wait while scaning  ?c:/windows/system...
- I have not yet figured out why my correction works ?
  $ESCAPECHAR ON
     Dim myDir As QDir
  $ESCAPECHAR OFF
  :) inheritance of compilation directive by a class ... :) in CONSTRUCTOR
  QDir.Inc is in $ESCAPECHARS ON mode from first to the last line !
  Last line being $ESCAPECHAR$ OFF

  But it's was work time here ! I'll look forward !

Jacques
Message17. Re: Still same problem :(
#617
Posted by: 2002-10-28 03:10:54
Hello,

I spent sometime on that QIRBUG this windy Sunday

It appears that  $ESCAPECHARS  scope is rather unpredictable when using
EXTENDED OBJECTS, the sequential compilation of rapidQ seems to be
broken when using EXTENDED OBJECTS ??????

Here is a bug test code

' --- code start --------
' -------------------------------------
''''''''''''''$ESCAPECHARS ON
$TYPECHECK ON
'
Type QBug Extends QObject
    PUBLIC:
    Function EscapePath (inPath As String) As String
        DefStr sInPath, sOutPath,
        sInPath = inPath
' ----------  Test 1  ----------  UNCOMMENT/COMMENT  TEST 1/2
'$ESCAPECHARS ON
'        sOutPath = ReplaceSubstr$(sInPath, "/", "\\")
'$ESCAPECHARS OFF
' ------------------------------
' ----------- Test 2  ----------
        sOutPath = ReplaceSubstr$(sInPath, "/", "")
' ------------------------------
        Result = sOutPath
    End Function
End Type
'
'''''''''''$ESCAPECHARS OFF
$TYPECHECK OFF
' -------------------------------------


' "RUNNING CODE"
' --------------
Const RQCR = Chr$(10)
$ESCAPECHARS ON             ' UNCOMMENT/COMMENT This line with TEST1/2
$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"

Dim myBug As QBug

Print myBug.EscapePath ("c:/dir1/dir2/filename")

' EXIT CONSOLE
' ------------
DefStr sExit
Print (RQCR & RQCR)
Input  "          CR to QUIT " , sExit
Print (RQCR & RQCR)
Application.Terminate
End
' ----------- Code End ---------

The best turn around for QDIR is to do this :

$ESCAPECHARS ON
   Dim myDir As QDir
$ESCAPECHAR$ OFF

If you dont use $ESCAPECHARS ON  in your code.

Jacques
Message18. QDIR update  Version 003
#619
Posted by: 2002-10-29 07:58:02
Hello,

A new version of QDIR available at :

   http://users.teledisnet.be/web/jph01696/qdirbeta003.zip

   Works too when $ESCAPECHARS is OFF now :)

All references to $ESCAPECHARS have been removed from QDIR_003

$ESCAPECHARS bug Demo :
   http://users.teledisnet.be/web/jph01696/bugescapechardemo.zip

Jacques
Message19. Re: QDIR update  Version 003
#621
Posted by: 2002-10-29 15:08:32
thanx.. I'll incorperate qdir in my program..
Message20. Re: QDIR update  Version 003
#622
Posted by: guidance 2002-10-29 18:25:50 Last edited by: guidance 2010-11-21 20:41:46 (Total edited 2 times)
Thanks!

By the way, the Rapid-Q area is an alternative place to release/announce your QDIR contribution too, welcome!



Guidance
Forum List • Thread List • Reply • Refresh • New Topic • Search • Previous • Next First 1 Last
掌柜推荐
 
 
 
 
 
 
 
 
 
 
 
 
© Sat 2024-4-20  Guidance Laboratory Inc.
Email:webmaster1g.yi.org Hits:0