Seeking a method to "read" a DOS directory

James E. Prior jep at oink.UUCP
Sat Mar 26 10:42:28 AEST 1988


In article <1001 at mcgill-vision.UUCP> mouse at mcgill-vision.UUCP (der Mouse) writes:
>In article <902 at cblpe.ATT.COM>, jrm at cblpe.ATT.COM (John Miller) writes:
>> I would like obtain a list of files that are in a DOS directory using
>> Microsoft 'C', version 4 or 5.

Sample code is included further down in this article.

I don't remember whether it was for Turbo C or usoft C.  It's very
similar either way.

>> The best method I know of so far [...] is to use a DOS interrupt
>> function to gain information about the FAT.  [and then read the disk
>> to find the directory]
>
>One of the DOS interrupts expands a wildcard name.  Tell it to expand
>*.* and you should get a list of everything.  (Actually, one entry
>tells it "get the first name matching this" and another says "get the
>next name matching the last thing I told you to look for", as I
>recall.)  Unfortunately, the match routine is rather badly broken.
>Asking for *C.*, for example, will return the same thing as *.*,
>regardless of whether the names in the directory contain `C'.  Or at
>least it did for me.  But for what you are doing, it should work to
>just give *.*.

MS-DOS (and its predecessor CP/M) treat wildcard characters differently
than UNIX.  This has bitten many a programmer learning one after the 
other.  MS-DOS and CP/M filenames have a first name and a last name.  
The first name can be up to eight characters.  The last name can be
up to three characters long.  The dot is always present whether you
like it or not.  i.e. writing to file "abcd" will be the same as file
"abcd." .  An asterisk will match any character (including void chars)
from its position in a name until the end of that name.  The first name
is treated separately from the last name in this matter.

Here's the code a friend gave me to do wildcard searches on a PC.  
I've never used it, so don't ask me anything about it.  Instead ask
Steve Crawford {ihnp4|osu-cis}!n8emr!oink!snc about it.

File readme.jim: ***********************************************************
Hey,

find_first and find_next are in file find3.asm

dofind.c is a little test program I wrote to see that it does
indeed work.  

Note in the beginning of find3.asm the db string called "fcb".
This is where the search pattern is defined; the ????????ASM matching
all files of type .ASM.  You must change this to be whatever you want.
There's probably a better way to do search patterns (like passing a search
string to the find_ routines), but this is exactly what I needed for my
purposes.  If either find_first or find_next don't find anything, they
return a 0.

The find_ routines were written for assembly under Microsoft Macro
Assembler V4.0 (or something like that).  The C program is for msc.
Enjoy, and remember me in your will.  Thanks for your help!!!

c'bag
File dofind.c: *************************************************************
#include <stdio.h>
#include <string.h>

char *fnames[20];

main()
{
	int i;
	char *ff,*sf;			/* storage for file names */
	char *malloc(),*find_first(), *find_next();

	sf=malloc(13);
	ff=find_first();
	strcpy(sf,ff);
	fnames[0]=sf;
	 
	for(i=1; (ff=find_next()); i++) {
	  sf=malloc(13);		/* get pointer to string */
	  strcpy(sf,ff);		/* copy file name */
	  fnames[i]=sf;			/* store pointer */
	}

	for(i=0; (fnames[i]); i++) {
	  printf("file %d = %s\n", i, fnames[i]);
	}
}
File find3.asm: **************************************************************
;
; find3.asm - find a file in the current directory
; 1/29/88 snc
;
; This is the third attempt.  This routine is callable from C, fills
; an external array with the found names, and returns a pointer to the
; last array element filled.
;
	DGROUP	GROUP _DATA
	ASSUME	DS:DGROUP
	_DATA	SEGMENT WORD PUBLIC 'DATA'
	sf	db	"NOT FOUND ON INT 11.$"
	no	db	"FILE DOES NOT EXIST.$"
	fcb	db	0,"????????ASM"
		db	25 dup(?)
	buffer	db	128 dup(?)
	fbuf	db	12 dup(?)		;file name buffer
	_DATA	ENDS

	P_ENTER	MACRO
		PUSH	BP
		MOV	BP,SP
		push	si
		push	di
		PUSH	ES
		push	ds
		mov	ax,DGROUP
		mov	ds,ax
		ENDM

	P_EXIT	MACRO
		pop	ds
		POP	ES
		pop	di
		pop	si
		mov	sp,bp
		POP	BP
		ENDM

	_TEXT	SEGMENT BYTE PUBLIC 'CODE'
	ASSUME	CS:_TEXT
	PUBLIC	_find_first, _find_next

	_find_first	PROC NEAR
	P_ENTER

	lea	dx,buffer		;create a DTA
	mov	ah,1ah			;set DTA function
	int	21h

	lea	dx,fcb			;do the search
	mov	ah,11h
	int	21h

	cmp	al,0ffh			;find it?
	jz	short not_found		;exit if not
	call	output			;else, fix up file name
	lea	ax,fbuf
	jmp	short done

not_found:
	xor	ax,ax			;if no match, return 0
done:
	P_EXIT
	ret
	_find_first	ENDP


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	_find_next	PROC NEAR
	P_ENTER

	lea	dx,fcb
	mov	ah,12h		;get next file
	int	21h
	cmp	al,0ffh		;no more files?
	jz	short no_more	;exit routine if so
	call	output

	lea	ax,fbuf
	jmp	short go_back
no_more:
	xor	ax,ax		;if no files, return 0
go_back:
	P_EXIT
	ret
	_find_next	ENDP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	output	PROC NEAR

	mov	si,1
	lea	bx,buffer
	lea	di,fbuf
outchar:
	mov	dl,[bx][si]
	cmp	dl,20h		;blank space?
	jz	short skip	;skip it if so
	mov	[di],dl		;store character
	inc	di
skip:
	inc	si
	cmp	si,9		;9 is 8 characters later from starting si
	jz	short period
	jmp	short outchar
period:
	mov	dl,2eh		;a period
	mov	[di],dl		;store character
	inc	di
outext:
	mov	dl,[bx][si]
	mov	[di],dl		;store character
	inc	di
	inc	si
	cmp	si,12
	jnz	short outext

	mov	[di],byte ptr 00	;null terminate string
	ret
	output	ENDP

	_TEXT	ENDS
	END
End of files ****************************************************************

Remember to thank/flame Steve Crawford for the code.

-- 
Jim Prior    {ihnp4|osu-cis}!n8emr!oink!jep    jep at oink.UUCP

Pointers are my friend.



More information about the Comp.sys.att mailing list