Ada Programming/Libraries/Ada.Directories

is a unit of the Predefined Language Environment since Ada 2005. It allows various manipulations and queries of the filesystem directories.

Introduction
If the environment supports the notion of files and directories, it is possible to manipulate these in a way that is fairly OS agnostic using the.

This is a very implementation dependent package and, as such, the information that can be extracted about files and directories is kept very basic. If further information is needed (owner, group, and so on), a child package should be created for this, as can be read in the implementation advice from the Ada Reference Manual :

"If other information about a file (such as the owner or creation date) is available in a directory entry, the implementation should provide functions in a child package Directories.Information to retrieve it."

Short Use Tutorial
This section gives a quick overview on the use of the  package. If it is not detailed enough, you can also follow the Detailed Use Tutorial.

Traversing Directories
Changing the current working directory is done with. The remaining functions are fairly self-explanatory with the exception of, which returns the name of the directory containing the given directory.

Current_Directory String Set_Directory Directory  String Exists Name  String  Boolean Containing_Directory Name  String  String

Enumerating Directory Entries
This example enumerates the all the entries in the current working directory, that end in ".gpr". The  procedure is used to start enumerating a directory. It will To remove the filter criteria you can pass an empty string. Iterating through the directory involves calling  to return the next directory entry and   to check for more entries. Once the search is complete, call.

Search_Type Directory_Entry_Type Start_Search Search      Search_Type Directory  String Pattern    String Filter     Filter_Type    True Get_Next_Entry Search   Search_Type Directory_Entry   Directory_Entry_Type More_Entries Search  Search_Type  Boolean End_Search Search   Search_Type

The resulting Directory_Entry_Type has a full name, simple name, size, kind, and modification type.

Simple_Name Directory_Entry  Directory_Entry_Type  String Full_Name Directory_Entry  Directory_Entry_Type  String Kind Directory_Entry  Directory_Entry_Type  File_Kind Size Directory_Entry  Directory_Entry_Type  File_Size Modification_Time Directory_Entry  Directory_Entry_Type  .Time

Main Dir Directory_Entry_Type Dir_Search Search_Type Curr_Dir string  Current_Directory Put"Current Directory: " Put_LineCurr_Dir Start_SearchSearch Dir_Search Directory Curr_Dir Pattern "*.gpr" Get_Next_EntryDir_Search Dir PutFull_NameDir Set_Col50 KindDir Ordinary_File PutSizeDir Set_Col60 Put_LineKindDir More_EntriesDir_Search End_SearchDir_Search Main

Directory Manipulation
Creating a directory is done with. creates all the directories in the path. The directory path on GNAT Ada can contain either "\" or "/" characters. renames a directory or file within a directory.  deletes an entire hierarchy of directories and files. deletes an empty directory (non-empty directories throw a  exception.    deletes an ordinary file in a directory.  Note that the   parameters is implementation specific.  On the version of GNAT Ada I'm using, it can only be used to set the encoding.

Create_Directory New_Directory  String Form   String  "" Create_Path New_Directory  String Form   String  "" Rename Old_Name New_Name  String

Delete_Tree Directory  String Delete_Directory Directory  String Delete_File Name  String

Below is a simple example that creates a set of directories and iterates through those directories. Note that it runs on both Windows and Linux with the "/" path separator. The returned path separators are appropriate to the filesystem (e.g. Windows return "\").

Main Dir Directory_Entry_Type Dir_Search Search_Type Start_SearchSearch Dir_Search Directory  Curr_Dir Pattern  "" Create_Path"Foo" Create_Path"Bar/Baz/Qux" Get_Next_EntryDir_Search Dir Put_LineFull_NameDir More_EntriesDir_Search End_SearchDir_Search Delete_Directory"Foo" Delete_Tree"Bar" Main

Exceptions
is raised if a directory entry is invalid or when enumerating directories past the last directory. is usually thrown if the directory or filename is not able to identify a file or directory (either non-existent or invalid depending on context). is thrown if directories are not supported or directories are not traversable.

Status_Error   .Status_Error Name_Error     Name_Error Use_Error      Use_Error Device_Error   Device_Error

Detailed Use Tutorial
This article will be based on a small program,, to which we will add functionality as we progress through the various functions, procedures, and types. In its most basic form, all it does is output the current default directory:

When running the above program, you should see output somewhat similar to this:

Starting default directory: /home/thomas/wiki_examples/aDir

Rather than the above path, you should see the path of the directory from which you launched  on your system.

Directory and File Operations
When working with files and directories, some basic functionality is required. We must be able to move to a specific directory; we must be able to copy, rename, and delete both files and directories; and we must be able to create new directories. Luckily, this is exactly what the next function and procedures enable us to do.

Current_Directory
The specification for  looks like this:

We've already seen how  works, but there are a few things yet that are worth mentioning about


 * returns the full directory name for the current default directory. This does not equal the directory where the program itself resides.
 * The directory name returned is suitable for use by the Set_Directory procedure.
 * The exception  is propagated if a default directory is not supported by the operating system/environment.

When we executed the basic  program above, the output was the path to where the   program resides on my system. But lets see what happens if we invoke the program from somewhere else:

$ pwd /home/thomas/wiki_examples/aDir $ ./adir Starting default directory: /home/thomas/wiki_examples/aDir $ cd && pwd /home/thomas $ wiki_examples/aDir/adir Starting default directory: /home/thomas

As you can see,  does not equal the path to the actual program. Instead it returns the current default directory, which is entirely implementation dependent. In the above example, it varies depending on where from the program is invoked. So unless you've specifically set the default directory using Set_Directory, you cannot be 100% sure what path  will return.

The second bullet-point is self-explanatory and the third is impossible for me to test, as I currently don't own a system that does not support the notion of a directory.

Set_Directory
The specification for  looks like this:

With  we're able to change the current default directory. Add this little bit of code to the body of the  program to see how it works:

If we execute the program now, we get this:

Starting default directory: /home/thomas/wiki_examples/aDir New default directory: /home/thomas

If the directory you're trying to set doesn't exist, a  is raised. Lets see how that works:

If you add the above snippet to the core  program, you will get output that looks something like this:

Starting default directory: /home/thomas/wiki_examples/aDir Directory does not exist.

Since the directory set by the  does not exist, the   exception is raised and caught. You should not, however, habitually use  to check if a given directory exists. For this simple task we have the Exists function.

Create_Directory
The specification for  looks like this:

With this procedure we can, to nobody's surprise, create new directories. But before we try it out, we will first deal with the  parameter. The RM has this to say about it:

"The Form parameter can be used to give system-dependent characteristics of the directory; the interpretation of the Form parameter is implementation-defined. A null string for Form specifies the use of the default options of the implementation of the new directory."

For my specific environment (Slackware 12.1 and GNATMAKE GPL 2008 compiler) the  parameter does precisely nothing. This might not be the case for other implementations, but I'm fairly certain that for most standard systems (Unix, Linux, BSD, Windows)  is not used. Thus,  should be a null string, unless you're on a platform where the implementation defines the use of.

But enough about that - lets add some code to  to see how   works:

With that one line of code added to the program, we can see how the program by doing a little test:

$ ls -l -rw-rw-rw- 1 thomas users   502 2009-09-24 22:09 Proj.gpr -rwxr-xr-x 1 thomas users 578199 2009-09-29 22:03 adir* -rw-rw-rw- 1 thomas users   517 2009-09-29 22:03 adir.adb drwxr-xr-x 2 thomas users     0 2009-09-29 22:03 objects/ $ ./adir Starting default directory: /home/thomas/wiki_examples/aDir $ ls -l -rw-rw-rw- 1 thomas users   502 2009-09-24 22:09 Proj.gpr -rwxr-xr-x 1 thomas users 578199 2009-09-29 22:03 adir* -rw-rw-rw- 1 thomas users   517 2009-09-29 22:03 adir.adb drwxr-xr-x 2 thomas users     0 2009-09-29 22:03 objects/ drwxr-xr-x 2 thomas users     0 2009-09-29 22:23 some_dir/ $ cd some_dir/ $ ../adir Starting default directory: /home/thomas/wiki_examples/aDir/some_dir $ ls -l drwxr-xr-x 2 thomas users 0 2009-09-29 22:25 some_dir/

As you can see from the above,  creates the new directory in the current default directory which, in this case, is the directory from where we invoke. In case we want to create the  directory in a directory other than the current default, we're going to have to add another line of code prior to the   line:

You should of course substitute the above path with something that fits your system.

Next we delete the already created  directories, and then we try the same chain of commands as before:

$ ls -l -rw-rw-rw- 1 thomas users   502 2009-09-24 22:09 Proj.gpr -rwxr-xr-x 1 thomas users 578224 2009-09-29 22:32 adir* -rw-rw-rw- 1 thomas users   635 2009-09-29 22:32 adir.adb drwxr-xr-x 2 thomas users     0 2009-09-29 22:32 objects/ $ ./adir Starting default directory: /home/thomas/wiki_examples/aDir $ ls -l -rw-rw-rw- 1 thomas users   502 2009-09-24 22:09 Proj.gpr -rwxr-xr-x 1 thomas users 578224 2009-09-29 22:32 adir* -rw-rw-rw- 1 thomas users   635 2009-09-29 22:32 adir.adb drwxr-xr-x 2 thomas users     0 2009-09-29 22:32 objects/ drwxr-xr-x 2 thomas users     0 2009-09-29 22:40 some_dir/ $ cd some_dir/ $ ../adir Starting default directory: /home/thomas/wiki_examples/aDir/some_dir raised ADA.IO_EXCEPTIONS.USE_ERROR : creation of new directory "some_dir" failed

Our program fails at creating the  directory the second time, because it already exists, proving that the program no longer creates   wherever we invoke the program. This is exactly what we wanted, though we should probably add some code to catch the exception, instead of just letting the program crash:

Now lets try that last command again:

$ ../adir Starting default directory: /home/thomas/wiki_examples/aDir/some_dir Directory cannot be created.

Much better!

Besides, there's also  , which is raised if the name given isn't a valid directory. Let's try and change  to something that is obviously not going to cut it as a directory name: An empty string. We just need to change one line in the program:

To

Now, running the program we get:

Starting default directory: /home/thomas/wiki_examples/aDir/some_dir raised ADA.IO_EXCEPTIONS.NAME_ERROR : invalid new directory path name ""

We can catch  by adding one more exception handler:

Running the program we now get this:

Starting default directory: /home/thomas/wiki_examples/aDir Directory is not valid.

Perfect.

Delete_Directory
The specification for  looks like this:

With  you can delete a directory which is empty and for which the program has sufficient permissions. The  parameter accepts both a single named directory or the full path to a directory. In the case of a single name, the current default directory is prepended to create a full path.

Add these lines to the basic  program to see it in action:

Executing this program, we get the following output:

$ ./adir Starting default directory: /home/thomas/wiki_examples/aDir New default directory: /home/thomas/wiki_examples/aDir some_dir exists. some_dir2 exists. $ ls -l -rw-rw-rw- 1 thomas users   502 2009-09-24 22:09 Proj.gpr -rwxr-xr-x 1 thomas users 578224 2009-09-30 16:13 adir* -rw-rw-rw- 1 thomas users   973 2009-09-30 16:14 adir.adb drwxr-xr-x 2 thomas users     0 2009-09-30 16:13 objects/

The example shows that  does indeed work with both the full path to the directory and with just the directory name. The two  calls are just there to help visualize the fact that the directories are, in fact, created.

The  exception is raised if the   string does not match an existing directory and the   exception is raised if the directory cannot be deleted or if it isn't empty. Add this code to the core  program:

And the output is:

Starting default directory: /home/thomas/wiki_examples/aDir Directory not found. Cannot delete non-empty directory.

As expected. In order to delete non-empty directories, you will have to use the Delete_Tree procedure.

Create_Path
The specification for  looks like this:

With  it is possible to create nested directories, even if the parent directories do not exist. It is much like issuing a  command, where the entire path is created, all the way down to the   directory.

Just as with its sibling, the   parameter is used for implementation specific characteristics. A null string specifies the use of the implementation's default options for creating new directories.

To create the directory  all we have to add to the   program is this:

And the output is:

Starting default directory: /home/thomas/wiki_examples/aDir this/is/a/new/directory exists!

If the path already exists when calling, the procedure simply do nothing.

works relative to the current default directory, unless the  given describes a path starting from the root of a filesystem, i.e. / for *nix systems and c:/ for a Windows system. To create the  in , all we have to do is add   to the   string:

So if the path is relative, the current default directory is used as the base, but if the path is absolute, the current default directory is ignored and the path is created entirely from the parameter.

The two exceptions,  and , are raised under the same circumstances as     if the   string does not identify a directory, and   if the program is not able to create any one of the directories, for example due to permission issues.

Delete_Tree
The specification for  looks like this:

enables us to delete directories and their contents in one fell swoop, so if we build on the example from Create_Path, we can delete the  tree by adding this to the program:

And the output is:

Starting default directory: /home/thomas/wiki_examples/aDir this/is/a/new/directory exists! this/is/a/new/directory does NOT exist!

The two exceptions  and   are also available to us. They work as expected, with  being raised if the   doesn't exist and   being raised if   can't be deleted for some reason or another. There's an important note about this behavior in the RM:

"The exception Use_Error is propagated if the external environment does not support the deletion of the directory or some portion of its contents with the given name (in the absence of Name_Error). If Use_Error is propagated, it is unspecified whether a portion of the contents of the directory is deleted."

It is important to pay special attention to the last sentence: it is unspecified whether a portion of the contents of the directory is deleted.

What this means, is that a  can be raised, but that wont necessarily mean that the directory and its contents are 100% intact. Some of it may very well have been deleted.

Finally, it should be mentioned that  looks for   in the current default directory, unless an absolute path is given.

Delete_File
The specification for  looks like this:

works much the same as Delete_Directory, it just deletes files instead of directories. Files, in the context of  can be either an ordinary file or a special file:

"External files may be classified as directories, special files, or ordinary files. A directory is an external file that is a container for files on the target system. A special file is an external file that cannot be created or read by a predefined Ada input-output package. External files that are not special files or directories are called ordinary files."

The usual exceptions also apply to.

Lets create a new file:

$ touch some_file

And now add this to the basic  program:

The output is:

Starting default directory: /home/thomas/wiki_examples/aDir some_file exists some_file does NOT exist

And the  file is gone.

Here's an example where we (A) don't have the proper permissions to delete the  file and (B) try to delete a non-existent file:

The output should look like this:

Starting default directory: /home/thomas/wiki_examples/aDir some_file exists Cannot delete some_file File does not exist some_file still exists

And with that, we conclude our look at.

Rename
The specification for  looks like this:

The  procedures renames both directories and files, providing that the   doesn't already exist. The  exception is raised if   does not match a directory or file, and   is raised if the directory/file cannot be renamed. In the following example, we will assume the existence of the directory  and the file.

First we will add a procedure to the declarative part of the  program:

This procedure is just a bit of sugar to the program. It's mainly here to avoid having to repeat the  block over and over.

Next we'll add a few lines to the body of the program:

The output from this is:

Starting default directory: /home/thomas/wiki_examples/aDir No, some_new_dir does not exist No, some_new_file does not exist Yes, some_new_dir exists Yes, some_new_file exists

Renaming files and directories just doesn't get any easier than this.

Copy_File
The specification for  looks like this:

copies the contents of an existing file,, to a new file named. The result is a duplicate of the source file. does not copy directories. Only ordinary files are copied. As noted earlier, the  parameter is only used if the implementation requires it. Here's what the RM has to say about :

"The Form parameter can be used to give system-dependent characteristics of the resulting external file; the interpretation of the Form parameter is implementation-defined."

In order to copy  to , all we have to do is add this line to the body of the   program:

Please note that if  already exists, it will be overwritten. The usual exceptions,  and , also apply to

is raised if a  or   does not properly identify a file. is raised if the action fails; the files are there, but for some other reason, copying is not possible.

Name Operations
The following six functions do not interact with the file system at all. They just manipulate strings. Armed with these functions, we are able to build file path strings, extract file names from paths, extract file extensions and discover the name of the directory containing a file.

Full_Name
The specification for  looks like this:

returns the full path to a given. The  parameter can be both a single filename, a relative path to a file or an absolute path. does not care about whether the file actually exists or not. It is only concerned with returning a proper full path. The RM has this to say about it:

"Returns the full name corresponding to the file name specified by Name. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file (including directories and special files)."

When I first read that, I thought that the sentence The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file meant that  would be raised if the given   parameter could not be resolved to an actual existing file. This is, however, not the case. Instead it means that  is raised if   is malformed.

Lets see how it works:

And the resulting output:

Starting default directory: /home/thomas/wiki_examples/aDir /home/thomas/wiki_examples/aDir/foo /home/thomas/wiki_examples/aDir/foo/bar /home/thomas/stuff New default directory: /tmp /tmp/foo /tmp/foo/bar /home/thomas/stuff Name parameter is malformed

As with all the other functions and procedures which depend on the current default directory, the  parameter is appended to the current default directory if   is relative, whereas the current default directory is ignored if   is an absolute path.

Simple_Name
The specification for  looks like this:

Where  returns the entire path to a file,   returns the simple name component of a path. So given the  parameter , it will return. The  exception is raised only if   is malformed. Lets see an example:

And the output is:

Starting default directory: /home/thomas/wiki_examples/aDir foo bar stuff Name parameter is malformed

Quite handy.

Containing_Directory
The specification for  looks like this:

removes the simple name of the  path given. Lets see it in action:

And the output is:

Starting default directory: /home/thomas/wiki_examples/aDir /home/thomas/wiki_examples/aDir foo /home/thomas Name_Error raised. Malformed Name. Use_Error raised. No containing directory.

As expected. Notice that the  is raised only when the given   parameter does not have a containing directory.

Extension
The specification for  looks like this:

If you want to extract the extension of a file, this function is what you need. Here's an example on usage:

And the output:

Starting default directory: /home/thomas/wiki_examples/aDir txt conf Name_Error raised. Malformed Name.

As you can see, if there are no extension (the foo/bar line), a null string is returned. The  exception is raised when the   parameter is malformed.

Base_Name
The specification for  looks like this:

I'm quite sure you've already guessed what  does, but indulge me in some example-code:

The output:

Starting default directory: /home/thomas/wiki_examples/aDir foo .secret bar stuff Name_Error raised. Malformed Name.

Notice the "odd" behavior in regards to the  file. Instead of returning the full  string, which is in fact the base name of the file, all we get is a null string. This might be considered somewhat weird, but it is in line with what the programmers of  intended. Here's a comment from the actual  function:

So there we have it, straight from the horse's mouth: If  returns a null string, you are probably dealing with a dot file, and you will have to parse it manually. So no, you cannot expect  to return the same results as for example the standard GNU tool. must work reliably across many platforms, thus the authors had to decide on a common, predictable, method. Returning a null string for dot files is just that, predictable.

Compose
The specification for  looks like this:

allows us to construct strings from directory paths, simple names and extensions. Some basic checks are made to ensure that the resulting string is syntactically sound. does not bother with the actual existence of the resulting path, it only cares about it's validity as a full name to a file.

Lets see how it works:

The output from the above is:

Starting default directory: /home/thomas/wiki_examples/aDir foo/bar.conf bar.conf /foo/bar /foo/bar.conf /foo/.conf .conf Name_Error raised. Malformed Name.

There's no surprise here.

The  exception is raised when:

"The exception Name_Error is propagated if the string given as Containing_Directory is not null and does not allow the identification of a directory, or if the string given as Extension is not null and is not a possible extension, or if the string given as Name is not a possible simple name (if Extension is null) or base name (if Extension is non-null)."

is quite handy when building string paths to a file. It's a far stretch better than just concatenating the strings yourself.

File and directory queries
The purpose of the following functions is obvious. With names such as,  ,   and   it shouldn't be too hard to guess what these functions do, so without further ado, lets dive in.

Exists
The specification for  looks like this:

If you want to know whether a file or a directory exists, you should use. We've already seen  in action in some of the previous examples, but let's see a snippet of code where   is the star of the show:

And the output:

Starting default directory: /home/thomas/wiki_examples/aDir some_file exists /home/thomas/wiki_examples/aDir/some_dir exists nonexistant_file does not exist Name_Error raised

As can be seen, the current default directory is taken into account if a relative path is given and  is raised when the given   is invalid as either a file or a directory, as is the case with the empty string in the above example. Other than that, there's not much to say about this function.

Kind
The specification for  looks like this:

In  files/directories are classified as one of three possible "file kinds": ,   or. A  is a file that is a container for other files. A  is a file that cannot be read or created by a predefined Ada input-output package. A File that is not either a  or a   is an.

Lets see how it works. First we must add a line of code to the declarative part of the  program:

And then the body:

And the output:

Starting default directory: /home/thomas/wiki_examples/aDir ORDINARY_FILE DIRECTORY SPECIAL_FILE Name_Error raised

honors the current default directory, just as all the other functions and procedures of. is raised if the given  parameter is invalid.

{{collapsible box|title=Ada.Directories.Kind Example Source|collapsed=yes|content=

Size
The specification for  looks like this:

The  type returned by   is an integer with the range. That is, on most systems, a very large number. With that noted,  does exactly what is expected of it:

And the result is:

Starting default directory: /home/thomas/wiki_examples/aDir 7  578580  Max File_Size on this system:  9223372036854775807

The size returned is the number of stream elements contained in the file, in this case 7 and 578580 bytes. The 9223372036854775807 number is there to show you how very large a number the  type can handle. I think we'd be hard pressed to find any kind of OS or file system that can handle files that large. Note that  is implementation dependent: It might be totally different on your system.

The usual  exception applies to   and you will also find a   if the file size is not of type , ie. it is either lower than 0 or higher than.

{{collapsible box|title=Ada.Directories.Size Example Source|collapsed=yes|content=

Modification_Time
The specification for  looks like this:

If you need to know what time a file was last modified, this is the function for it. As you can see, it returns an  object, so to actually see the output, we need to add a   clause and an extra line to the declarative part of. First the  clause:

And then the declaration:

And finally the code that goes into the body:

The output from this little snippet is:

Starting default directory: /home/thomas/wiki_examples/aDir 2009-10-06 14:10:04

The usual  is raised if the file is invalid and a   is raised if the environment doesn't support the notion of modification time on a file.

{{collapsible box|title=Ada.Directories.Modification_Time Example Source|collapsed=yes|content=

Directory Searching
Searching over a directory structure is done using the following types and subprograms. In the previous sections we haven't really bothered with the types, as they didn't really play an active role in using the functions and procedures, but with searching things are a bit different: Here we actively use the types to keep track of the state of a search and the result of a search.

Searching can be done either using an active or a passive iterator. The active iterator approach is merely a simple loop and the passive iterator is done using access to a subprogram that defines what to do with each result of the search. We will show how both methods work.

Directory_Entry_Type
The specification for  looks like this:

The  represents a single item in a directory. The only way to create a  is by using the Get_Next_Entry procedure. One such  object can then be used by appropriate subprograms, such as Simple_Name, Kind and so on. It should be obvious from the  record what kind of information we can extract from it.

Filter_Type
The specification for  looks like this:

There are three different kinds of files in  ,   and. With  you define which of these you wish to search for:

Here we setup a filter that ignores  and allows   and.

Search_Type
The specification for  looks like this:

contains the state of the search. You initialize the  object with Start_Search, you check it with More_Entries, you read it with Get_Next_Entry and you clean it up with End_Search.

Start_Search
The specification for  looks like this:

All the searching related types and subprograms depend heavily on each other. Because of that, I believe it will make the most sense to present a complete program that encompass them all. This means that we will deviate from the usual  program, and instead go with this:

The output from this program, when run on my system, is:

/home/thomas/wiki_examples/aDir/adir .                      dir                 2009-10-23 20:17:22      /home/thomas/wiki_examples/aDir/. ..                     dir                 2009-09-24 20:07:57      /home/thomas/wiki_examples/aDir/.. objects                dir                 2009-10-27 20:56:32      /home/thomas/wiki_examples/aDir/objects Proj.gpr               502 bytes           2009-09-24 20:09:20      /home/thomas/wiki_examples/aDir/Proj.gpr adir                   594193 bytes        2009-10-23 20:17:22      /home/thomas/wiki_examples/aDir/adir some_dir               dir                 2009-10-06 14:10:25      /home/thomas/wiki_examples/aDir/some_dir adir.adb               1781 bytes          2009-10-23 20:17:21      /home/thomas/wiki_examples/aDir/adir.adb some_file              7 bytes             2009-10-06 14:10:04      /home/thomas/wiki_examples/aDir/some_file some_new_file          7 bytes             2009-10-06 14:37:15      /home/thomas/wiki_examples/aDir/some_new_file

sets the stage for a search. It takes four parameters:  which contains the state of the search,   which is the directory to search,   which is a, well, pattern for matching filenames and   which defines the kinds of files that are returned by the search.

The interpretation of the  value is implementation defined, except that an empty string equals "match everything". It is highly probable that simple and well-known patterns like  will yield the expected result: All files with the   extension are matched.

In this case we search for everything (empty  string) that isn't considered a   (Filter is assigned  ) in the current directory.

The above program uses an active iterator: The  loop. As you can see, this loop goes on as long as  is. When this is no longer the case, the loop ends and we call  to clean up the   object. This basically resets it, so it no longer contains any entries.

We can avoid having to manage such basic house-keeping if we instead use a passive iterator. Here's what the program looks like when using a passive iterator:

The output is:

/home/thomas/wiki_examples/aDir/adir .                      dir                 2009-10-23 20:17:22      /home/thomas/wiki_examples/aDir/. ..                     dir                 2009-09-24 20:07:57      /home/thomas/wiki_examples/aDir/.. objects                dir                 2009-10-27 20:56:32      /home/thomas/wiki_examples/aDir/objects Proj.gpr               502 bytes           2009-09-24 20:09:20      /home/thomas/wiki_examples/aDir/Proj.gpr adir                   594193 bytes        2009-10-23 20:17:22      /home/thomas/wiki_examples/aDir/adir some_dir               dir                 2009-10-06 14:10:25      /home/thomas/wiki_examples/aDir/some_dir adir.adb               1781 bytes          2009-10-23 20:17:21      /home/thomas/wiki_examples/aDir/adir.adb some_file              7 bytes             2009-10-06 14:10:04      /home/thomas/wiki_examples/aDir/some_file some_new_file          7 bytes             2009-10-06 14:37:15      /home/thomas/wiki_examples/aDir/some_new_file

With the passive iterator, you get rid of the  and the   ->   ->   ->   chain. It is much cleaner and less error-prone, because you don't have to worry about forgetting the final  call. Both methods have their advantages though, so use whatever is the best fit for the situation.

The  procedure accepts almost the same parameters as , except that we have   instead of. is of course access to the subprogram that is to handle each item returned by the search. This subprogram must accept one parameter:.

{{collapsible box|title=Ada.Directories.Start_Search Example Source|collapsed=yes|content=

End_Search
The specification for  looks like this:

is a clean-up procedure. It is only necessary to use  if you've called   earlier. It is used to reset the, effectively clearing out all search entries.

Typical usage would look something like this:

An actual usage example can be found here.

More_Entries
The specification for  looks like this:

is only relevant if a prior call to  has been made. A call to  return boolean   if more entries are available on a call to. Otherwise boolean  is returned. See Start_Search for an actual usage example.

Get_Next_Entry
The specification for  looks like this:

I'm just going to quote the Ada Reference Manual on

"Returns the next Directory_Entry for the search described by Search that matches the pattern and filter. If no further matches are available, Status_Error is raised. It is implementation-defined as to whether the results returned by this routine are altered if the contents of the directory are altered while the Search object is valid (for example, by another program). The exception Use_Error is propagated if the external environment does not support continued searching of the directory represented by Search."

How this works, can be seen in the Start_Search section.

Simple_Name (Directory Entries)
The specification for  looks like this:

The functionality of this  function is exactly the same as the "regular" Simple_Name function, except it accepts a   instead of a   for the   parameter. See Start_Search for an example.

Full_Name (Directory Entries)
The specification for  looks like this:

The functionality of this  function is exactly the same as the "regular" Full_Name function, except it accepts a   instead of a   for the   parameter. See Start_Search for an example.

Kind (Directory Entries)
The specification for  looks like this:

The functionality of this  function is exactly the same as the "regular" Kind function, except it accepts a   instead of a   for the   parameter. See Start_Search for an example.

Size (Directory Entries)
The specification for  looks like this:

The functionality of this  function is exactly the same as the "regular" Size function, except it accepts a   instead of a   for the   parameter. See Start_Search for an example.

Modification_Time (Directory Entries)
The specification for  looks like this:

The functionality of this  function is exactly the same as the "regular" Modification_Time function, except it accepts a   instead of a   for the   parameter. See Start_Search for an example.

Specification
Current_Directory String Set_Directory Directory  String Create_Directory New_Directory  String Form           String  "" Delete_Directory Directory  String Create_Path New_Directory  String Form           String  "" Delete_Tree Directory  String Delete_File Name  String Rename Old_Name  String New_Name  String Copy_File Source_Name  String Target_Name  String Form         String  "" Full_Name Name  String  String Simple_Name Name  String  String Containing_Directory Name  String  String Extension Name  String  String Base_Name Name  String  String Compose Containing_Directory  String  "" Name                  String Extension             String  "" String File_Kind Directory Ordinary_File Special_File File_Size  0  implementation_defined Exists Name  String  Boolean Kind Name  String  File_Kind Size Name  String  File_Size Modification_Time Name  String  AdaCalendarTime Directory_Entry_Type Filter_Type  File_Kind  Boolean Search_Type Start_Search Search       Search_Type Directory       String Pattern         String Filter          Filter_Type    True End_Search Search   Search_Type More_Entries Search  Search_Type  Boolean Get_Next_Entry Search            Search_Type Directory_Entry     Directory_Entry_Type Search Directory  String Pattern    String Filter     Filter_Type    True Process Directory_Entry  Directory_Entry_Type Simple_Name Directory_Entry  Directory_Entry_Type String Full_Name Directory_Entry  Directory_Entry_Type String Kind Directory_Entry  Directory_Entry_Type File_Kind Size Directory_Entry  Directory_Entry_Type File_Size Modification_Time Directory_Entry  Directory_Entry_Type AdaCalendarTime Status_Error   AdaIO_ExceptionsStatus_Error Name_Error     AdaIO_ExceptionsName_Error Use_Error      AdaIO_ExceptionsUse_Error Device_Error   AdaIO_ExceptionsDevice_Error Import Ada Directory_Entry_Type Import Ada Search_Type AdaDirectories

Wikibook

 * Ada Programming/Libraries/Ada

Open-Source Implementations
Libraries:Ada.Directories

Programación en Ada/Unidades predefinidas/Ada.Directories