{{fbdoc item="title" value="DIR"}}----
Searches for and returns information about an item in the filesystem; performs a directory searchattrib

{{fbdoc item="syntax"}}##
	# [[KeyPgInclude|include]] "dir.bi"
	
	[[KeyPgDeclare|declare]] [[KeyPgFunction|function]] **Dir** ( [[KeyPgByref|byref]] //item_spec// [[KeyPgAs|as]] [[KeyPgConstQualifier|const]] [[KeyPgString|string]], [[KeyPgByval|byval]] //attrib_mask// [[KeyPgAs|as]] [[KeyPgInteger|integer]] = **fbNormal**, [[KeyPgByref|byref]] //out_attrib// [[KeyPgAs|as]] [[KeyPgInteger|integer]] ) [[KeyPgAs|as]] [[KeyPgString|string]]
	[[KeyPgDeclare|declare]] [[KeyPgFunction|function]] **Dir** ( [[KeyPgByref|byref]] //item_spec// [[KeyPgAs|as]] [[KeyPgConstQualifier|const]] [[KeyPgString|string]], [[KeyPgByval|byval]] //attrib_mask// [[KeyPgAs|as]] [[KeyPgInteger|integer]] = **fbNormal**, [[KeyPgByval|byval]] //p_out_attrib// [[KeyPgAs|as]] [[KeyPgInteger|integer]] [[KeyPgPtr|ptr]] = 0 ) [[KeyPgAs|as]] [[KeyPgString|string]]
	[[KeyPgDeclare|declare]] [[KeyPgFunction|function]] **Dir** ( [[KeyPgByref|byref]] //out_attrib// [[KeyPgAs|as]] [[KeyPgInteger|integer]] ) [[KeyPgAs|as]] [[KeyPgString|string]]
	[[KeyPgDeclare|declare]] [[KeyPgFunction|function]] **Dir** ( [[KeyPgByval|byval]] //p_out_attrib// [[KeyPgAs|as]] [[KeyPgInteger|integer]] [[KeyPgPtr|ptr]] = 0 ) [[KeyPgAs|as]] [[KeyPgString|string]]
##
{{fbdoc item="usage"}}##
	//result// = **Dir**( //item_spec//, [ //attrib_mask// ], //out_attrib// )
	//result// = **Dir**( //item_spec// [, [ //attrib_mask// ] [, //p_out_attrib// ] ] )
	//result// = **Dir**( //out_attrib// )
	//result// = **Dir**( [ //p_out_attrib// ] )
##
{{fbdoc item="param"}}
	##//item_spec//##
		The pattern to match an item's name against.
	##//attrib_mask//##
		The bit mask to match an item's attributes against.
	##//out_attrib//##
		Reference to a bit mask that's assigned each of the found item's attributes, if any.
	##//p_out_attrib//##
		Pointer to a bit mask that's assigned each of the found item's attributes, if any.

{{fbdoc item="ret"}}
	If no item matching the name ##//item_spec//## or the attribute mask ##//attrib_mask//## was found, then ##//out_attrib//## (or ##*//p_out_attrib//##) is assigned to zero and an empty string is returned. Otherwise, ##//out_attrib//## (or ##*//p_out_attrib//##) is assigned the attribute mask of the item, and the item name, without a path, is returned.

{{fbdoc item="desc"}}
	##**Dir**## returns the first filesystem item that matches the ##//item_spec//## passed as an argument. To retrieve the next file items that match this ##//item_spec//## pattern, call ##**Dir**## again without this argument (or with an empty string).
	So to obtain a list of items in a directory, ##**Dir**## needs to be invoked multiple times returning one item per invocation.
	
	If ##//item_spec//## contains an absolute path, then the first procedure searches the filesystem for an item that matches the name ##//item_spec//## and whose attributes are all contained in ##//attrib_mask//## (##fbNormal## by default). Otherwise, it searches relative to the current directory (see ##[[KeyPgCurdir|CurDir]]##). In any case, if a matching item is not found, ##//out_attrib//## is assigned to zero and an empty string is returned. Otherwise, ##//out_attrib//## is assigned with the attribute flags of the item, and the name of the item, without a path, is returned.
	##//item_spec//## may include an asterisk (##*##, for matching any adjacent characters) or one or more question marks (##?##, for matching any individual character). If it does, the procedure searches for the first such item.
	
	If an item is found, subsequent calls with ##//item_spec//## omitted, or set to an empty string, will return the next item matching the name ##//item_spec//## until no more such items are found. If ##//attrib_mask//## is omitted from these subsequent calls, the procedure searches for items with the same attributes as in the previous call.
	
	The second syntax behaves the same as ##**Dir**( //item_spec//, //attrib_mask//, *//p_out_attrib// )##.
	The third syntax behaves the same as ##**Dir**( "####", , //out_attrib// )##.
	The fourth syntax behaves the same as ##**Dir**( "####", , *//p_out_attrib// )##.

**File Attributes:**
	Files and directories and other items can be said to possess so-called file attributes; metadata that describes the item. The meaning of this metadata may vary depending on the operating system and the file system it uses.
	The following defined constants are used as bit-flags in ##//attrib_mask//## and in ##//out_attrib//## or ##*//p_out_attrib//##. Their values can be combined to form a mask using ##[[KeyPgOpOr|Operator Or]]##. These values are the metadata that the returned files are **allowed** to have. To access the defined flags, you must ##[[KeyPgInclude|#Include]] "dir.bi"##.
	
	Assuming the reader understands 'file' to mean any file system entry: normal file, directory, etc.
	##//attrib_mask//## specifies the set of file attributes that are permitted for file names returned (if a file has an attribute that is not specified in ##//attrib_mask//##, then it is excluded from file names returned).
	For example:
		##fbDirectory## will only allow the directory attribute not to be set, meaning that only files or directories with no other attributes set will be matched.
		##(fbReadOnly [[KeyPgOpOr|Or]] fbDirectory)## will allow read-only directories and files, and writable directories and files.
		##//fbArchive// [[KeyPgOpOr|Or]] //fbDirectory//## will match against archived files, archived directories, non-archived files and non-archived directories (it will not match against, for example, read-only files).
	Logic condition:
			file name returned by ##**DIR**## if the equality ##'((attrib_mask) OR (file_attrib)) = (attrib_mask)'## is true
		or
			file name returned by ##**DIR**## if ##((file_attrib) AND (Not attrib_mask)) = 0##
			
	More powerful filtering can be done by checking the returned ##//out_attrib//## for specifc flags using ##[[KeyPgOpAnd|Operator And]]##.
	
	## # define fbReadOnly &h01 ##
		//The item cannot be written to or deleted.//
		**DOS & Windows**: The item has the "read-only" attribute set.
		**Linux**:The item has no write permissions associated with the current user or group, nor is it globally writable.  (Whether or not the user has root permissions is ignored.)
		
	## # define fbHidden &h02 ##
		//The item is hidden in ordinary directory listings.//
		**DOS & Windows**: The item has the "hidden" attribute set.
		**Linux**: The item's name has a period (##.##) as the first character.
		
	## # define fbSystem &h04 ##
		//The item is used almost exclusively by the system.//
		**DOS & Windows**: The item has the "system" attribute set.
		**Linux**: The item is either a character device, block device, named pipe (FIFO) or Unix socket.
		
	## # define fbDirectory &h10 ## 
		//The item is a directory. Includes the current (##.##) and parent (##..##) directories as well.//
		**DOS & Windows & Linux**: The item is a directory.
		
	## # define fbArchive &h20 ##
		//The item may be backed up after some automated operations.//
		**DOS & Windows**: The item has the "archive" attribute set (automatically set after every write access to a file).
		**Linux**: The item is not a directory; typical filesystems do not support this metadata.
		
	## # define fbNormal (fbReadOnly or fbArchive) ##
		//The item is read-only or "archived".//
		
	(If ##//attrib_mask//## does not include ##**fbArchive**##, then ##**Dir**## may widen the check to include ##**fbDirectory**##, but it is recommended to add ##**fbDirectory**## explicitly, if that is the behaviour sought.)
	
	Items found having no attributes are **always** matched, regardless of the value of ##//attrib_mask//##.
	An item will not be matched if it has one or more attributes that aren't specified in ##//attrib_mask//##.
	
	In general it is not possible to use ##//attrib_mask//## to include a file/folder with one set of attributes while excluding a file/folder with a different set. For example, it is not possible to scan for read-only directories while excluding read-only files (unless the files also have other attributes).
	Finer control can be gained by checking the ##//out_attrib//## value for the desired set of attributes.

{{fbdoc item="ex"}}
	{{fbdoc item="filename" value="examples/manual/system/dirnbfiles.bas"}}%%(freebasic)
' Number of files in the current directory.

Dim As Integer FileCount

If Dir("*") <> "" then  ' Start a file search with no specified filespec/attrib *AND* get the first filename.
	Filecount = 1
	While Dir() <> ""  ' If dir() is "", exit the loop: no more filenames are left to be read.
		FileCount += 1  ' Increment the counter of number of files
	Wend
End If

Print FileCount & " files in the current directory."

Sleep
%%	
	
	{{fbdoc item="filename" value="examples/manual/system/dir.bas"}}%%(freebasic)
#include "dir.bi" 'provides constants to use for the attrib_mask parameter

sub list_files (byref filespec as string, byval attrib as integer)
	dim as string filename = dir(filespec, attrib) ' Start a file search with the specified filespec/attrib *AND* get the first filename.
	do while len(filename) > 0 ' If len(filename) is 0, exit the loop: no more filenames are left to be read.
		print filename
		filename = dir() ' Search for (and get) the next item matching the initially specified filespec/attrib.
	loop
end sub

print "directories:"
list_files "*", fbDirectory

print
print "archive files:"
list_files "*", fbArchive
%%	
	
	{{fbdoc item="filename" value="examples/manual/system/dirfolder.bas"}}%%(freebasic)
'' show any files that have directory attribute and don't care if it is system, hidden, read-only, or archive

#include once "dir.bi"

'' allow everything
var mask = fbDirectory or fbHidden or fbSystem or fbArchive or fbReadOnly

var attrib = 0
var f = dir( "*.*", mask, attrib )
while( f > "" )
	'' show any files that have at least a directory attribute
	if( attrib and fbDirectory ) then
		print f
	end if
	f = dir( attrib )
wend
%%	
	
	{{fbdoc item="filename" value="examples/manual/system/dirretat.bas"}}%%(freebasic)
'' Example of using DIR function and retrieving attributes

#include "dir.bi" '' provides constants to match the attributes against

'' set input attribute mask to allow files that are normal, hidden, system or directory
Const attrib_mask = fbNormal Or fbHidden Or fbSystem Or fbDirectory ' = &h37

Dim As UInteger out_attr '' unsigned integer to hold retrieved attributes

Dim As String fname '' file/directory name returned with
Dim As Integer filecount, dircount

fname = Dir("*.*", attrib_mask, out_attr) '' Get first file name/attributes, according to supplied file spec and attribute mask

Print "File listing in " & CurDir & ":"

Do Until Len(fname) = 0 '' loop until Dir returns empty string

	If (fname <> ".") And (fname <> "..") Then '' ignore current and parent directory entries

		Print fname,

		If (out_attr And fbDirectory) <> 0 Then
			Print "- directory";
			dircount += 1
		Else
			Print "- file";
			filecount += 1
		End If
		If (out_attr And fbReadOnly) <> 0 Then Print ", read-only";
		If (out_attr And fbHidden  ) <> 0 Then Print ", hidden";
		If (out_attr And fbSystem  ) <> 0 Then Print ", system";
		If (out_attr And fbArchive ) <> 0 Then Print ", archived";
		Print

	End If

	fname = Dir(out_attr) '' find next name/attributes

Loop

Print
Print "Found " & filecount & " files and " & dircount & " subdirs"
%%
{{fbdoc item="target"}}
	- Linux requires the ##//filename//## case to match the real name of the file. Windows and DOS are case insensitive.
	- Path separators in Linux are forward slashes ##/##. Windows uses backslashes ##\## but it allows for forward slashes.  DOS uses backslashes.
	- In DOS, the attrib mask value of ##&h37## (##&h3F## usually works also, but ##&h37## is safer) returns all files and directories, including "." and "..", but no Volume: the value ##8## returns the Volume, even if current directory is not the main directory.

{{fbdoc item="lang"}}
	- Not available in the //[[CompilerOptlang|-lang qb]]// dialect unless referenced with the alias ##**""__Dir""**##.

{{fbdoc item="diff"}}
	- Not found in ""QBasic"" but present in Visual Basic.  The ##//out_attrib//## parameter is new to ""FreeBASIC"".

{{fbdoc item="see"}}
	- ##[[KeyPgOpen|Open]]##
	- ##[[KeyPgCurdir|Curdir]]##
	- ##[[KeyPgChdir|Chdir]]##
	- ##[[KeyPgMkdir|Mkdir]]##
	- ##[[KeyPgRmdir|Rmdir]]##

{{fbdoc item="back" value="CatPgOpsys|Operating System Functions"}}