Test if a directory exists

Anything QL Software or Programming Related.
User avatar
Andrew
Aurora
Posts: 786
Joined: Tue Jul 17, 2018 9:10 pm

Test if a directory exists

Post by Andrew »

Ho do you test if a directory exists ?
FOP_DIR does not seem to work.
If i try
c%=FOP_DIR('win2_XYZ'_): Print c%
it returns a positive number even if the directory win2_XYZ_ does not exist - it simply opens a channel to win2_

If i try
c%=FOP_DIR('win27_XYZ'_): Print c%
it returns a positive number even if the drive win27_ cannot exist - it simply opens a channel to the default drive

So how can you check if a directory exists or not ?


RWAP
RWAP Master
Posts: 2834
Joined: Sun Nov 28, 2010 4:51 pm
Location: Stone, United Kingdom
Contact:

Re: Test if a directory exists

Post by RWAP »

Yes - this is unfortunate - Note 4 on OPEN_DIR in the SBASIC/SuperBASIC Reference Manual refers to it:

https://superbasic-manual.readthedocs.i ... l#open-dir

I don't recall finding a solution (does setting DATA_USE "" help?)

From memory I could not think of a situation where you needed to do this - there is a backup routine in the examples for FBKDT which works the opposite way - starting at the drive and stepping through sub-directories as it goes...

https://superbasic-manual.readthedocs.i ... ists#fbkdt


User avatar
Andrew
Aurora
Posts: 786
Joined: Tue Jul 17, 2018 9:10 pm

Re: Test if a directory exists

Post by Andrew »

Setting DATA_USE "" does not help - FOP_DIR will open a channel to the drive and will not return -7 :(
I have read about OPEN_DIR and FBKDT - in fact i have started from the OPEN_DIR example and refined it a bit. And I have a couple of cases where it would be nice to check if a directory or a file exists.
Of course, there always are work-arounds - but starting from the drive and parsing the directory tree is a bit time consuming and i wanted to avoid that.
(just for fun I am writing sort of a Norton Commander for the QL)

By the way, DJ_OPEN_DIR has the same behavior and limitations.


User avatar
tofro
Font of All Knowledge
Posts: 2685
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: Test if a directory exists

Post by tofro »

The behavior you see has to do with the fact that opening a directory on a valid and working device may not fail on QDOS for reasons other than the file exists and is no directory (That has to do with the fact that directories were a late addition to the OS and also somewhat with the way the default drives and directories work in QDOS) - If the directory you asked for didn't open, the driver will open the directory "next up" for you, walking upwards to the root in case that fails.

What you can always do is:

  • Open the directory
  • Check the name of what has been opened against your desired name

Code: Select all

FUNCTION DirExists (name$)
LOCAL channel, realName$
    channel = FOP_DIR (name$)
    realName$ = FNAME$ (#channel)
    CLOSE #channel
    IF realName$ == name$ THEN
       RETURN 1
    ENDIF
    RETURN 0
ENDDEF
   
Though this might still fail on aliased devices like dev_ and pth_, it is much better than nothing.

Tobias
Last edited by tofro on Fri Oct 05, 2018 11:39 pm, edited 2 times in total.


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
dilwyn
Mr QL
Posts: 2753
Joined: Wed Dec 01, 2010 10:39 pm

Re: Test if a directory exists

Post by dilwyn »

I suppose you could try something like this, but only on a level 2 filing system.

100 drive$ = 'win1_':direc$ = 'xyz'
110 ch = FOP_DIR(drive$&direc$)
120 IF FNAME$(#ch) == direc$ THEN
130 PRINT direc$;' exists'
140 ELSE
150 PRINT direc$;' does not exist'
160 END IF
170 CLOSE

or alternatively, use the FMAKE_DIR function version of MAKE_DIR (not all file systems have FMAKE_DIR) to try to create the directory:

er = FMAKE_DIR('win1_xyz_')
IF er = -8 THEN PRINT 'xyz already exists'

On systems not having FMAKE_DIR, you could try error trapping a MAKE_DIR statement, e.g. with Q_ERR_ON 'make_dir' from QLiberator, or a WHEN_ERROR in Turbo.


User avatar
tofro
Font of All Knowledge
Posts: 2685
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: Test if a directory exists

Post by tofro »

Dilwyn,

working with FMAKE_DIR or MAKE_DIR is a bit of a dangerous path. It will work in theory, but you will run into hard to fix issues in case the driver has to move files into that newly made directory:

win1_LETTER_TXT exists,
win1_LETTER_DOC exists

you try to find out whether the directory win1_letter exists

FMAKE_DIR will end you up with a directory named win1_letter and two files named txt and doc in it, and you will have a very hard time getting rid of that directory again.

Tobias


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
Andrew
Aurora
Posts: 786
Joined: Tue Jul 17, 2018 9:10 pm

Re: Test if a directory exists

Post by Andrew »

tofro wrote:The behavior you see has to do with the fact that opening a directory on a valid and working device may not fail on QDOS for reasons other than the file exists and is no directory (That has to do with the fact that directories were a late addition to the OS and also somewhat with the way the default drives and directories work in QDOS) - If the directory you asked for didn't open, the driver will open the directory "next up" for you, walking upwards to the root in case that fails.

What you can always do is:

  • Open the directory
  • Check the name of what has been opened against your desired name

Code: Select all

FUNCTION DirExists (name$)
LOCAL channel, realName$
    channel = FOP_DIR (name$)
    realName$ = FNAME$ (#channel)
    CLOSE #channel
    IF realName$ == name$ THEN
       RETURN 1
    ENDIF
    RETURN 0
ENDDEF
   
Though this might still fail on aliased devices like dev_ and pth_, it is much better than nothing.

Tobias
No, it does not work :cry:
if name$='win2_xyzzy_' then realname$ will be always be 'xyzzy_' regardless of it's existence
FNAME$ just removes the drive from the name


Derek_Stewart
Font of All Knowledge
Posts: 3932
Joined: Mon Dec 20, 2010 11:40 am
Location: Sunny Runcorn, Cheshire, UK

Re: Test if a directory exists

Post by Derek_Stewart »

Hi,

I use the Toolkit 2 Function FTEST which tests for the existence of a file.

Since a directory is a file with type 255, then using:

PRINT FTEST("win1_dir")

would produce 0 if the directory / file exists or -7 if not exists.

Then use FTYP to test for the file type.


Regards,

Derek
User avatar
dilwyn
Mr QL
Posts: 2753
Joined: Wed Dec 01, 2010 10:39 pm

Re: Test if a directory exists

Post by dilwyn »

tofro wrote:Dilwyn,

working with FMAKE_DIR or MAKE_DIR is a bit of a dangerous path. It will work in theory, but you will run into hard to fix issues in case the driver has to move files into that newly made directory:

win1_LETTER_TXT exists,
win1_LETTER_DOC exists

you try to find out whether the directory win1_letter exists

FMAKE_DIR will end you up with a directory named win1_letter and two files named txt and doc in it, and you will have a very hard time getting rid of that directory again.

Tobias
That's just the usual cr*p of how the QL filing system works of course. That and trying to sensibly handle the intricacies of the DEVs, PTHs and SUBs of this world are impractical for most QL software.

It depends if Andrew's requirement is to error trap a directory creation - to prevent trying to create one if already exists. In that case error trapping a MAKE_DIR or FMAKE_DIR is the best solution.

If what Andrew is trying to do is strictly just check if a diretory name exists without creating one, the FNAME$ method is better as long as you separate the drive and directory name for the test (as Andrew found).

If none of these methods fulfil what Andrew wants, he'll in all likelihood have to resort to scanning the directory tree for the directory name, though even that probably won't achieve much more than the FNAME$ method.

The other aspect of this is simply checking if the system supports directories in the first place. There are probably two methods of doing this, firstly scan the BASIC name table for a MAKE_DIR command (e.g. use EXTRAS#channel to send a list of extensions to a file, read it back and look for MAKE_DIR), or secondly use an extension such as LEVEL2 in DJToolkit to test if the system supports level 2 directories. it works by calling IOF.XINF in interrogate mode [d2.b=0 - not documented in QDOS/SMS guide] to see if the extended system information is returned or not. To study it, just search for IOF.XINF in the DJToolkit_asm sources.


User avatar
dilwyn
Mr QL
Posts: 2753
Joined: Wed Dec 01, 2010 10:39 pm

Re: Test if a directory exists

Post by dilwyn »

Derek_Stewart wrote:Hi,

I use the Toolkit 2 Function FTEST which tests for the existence of a file.

Since a directory is a file with type 255, then using:

PRINT FTEST("win1_dir")

would produce 0 if the directory / file exists or -7 if not exists.

Then use FTYP to test for the file type.
Thanks Derek. Nice simple solution. Coded as a function like this:

Code: Select all

1000 DEFine FuNction DIR_EXISTS (name$)
1010   LOCal er
1020   IF FTEST(name$) = 0 THEN
1030     IF FTYP(\name$) = 255 THEN er = 1 : ELSE er = 0 : END IF
1040   ELSE
1050     er = 0
1060   END IF
1070   RETurn er
1080 END DEFine DIR_EXISTS
It'll return 1 if a directory exists, 0 if not. name$ should be drive+directory name or the DATAD$ default might upset things.


Post Reply