File Paths in Ada

The Ada.Directories package provides functions to parse and construct file paths in a way that is portable between operating systems.

with Ada.Text_IO;
with Ada.Directories;
with Ada.Strings.Fixed;

procedure File_Paths is
   use Ada.Text_IO;
   use Ada.Directories;
   use Ada.Strings.Fixed;

   P : String := Compose("dir1", "dir2", "filename");
begin
   -- Compose should be used to construct paths in a portable way.
   -- It takes any number of arguments and constructs a hierarchical path from them.
   Put_Line("p: " & P);

   -- You should always use Compose instead of concatenating '/'s or '\'s manually.
   -- In addition to providing portability, Compose will also normalize paths
   -- by removing superfluous separators and directory changes.
   Put_Line(Compose("dir1//", "filename"));
   Put_Line(Compose("dir1/../dir1", "filename"));

   -- Containing_Directory and Simple_Name can be used to split a path to the
   -- directory and the file. There's no direct equivalent to Split in Ada.
   Put_Line("Containing_Directory(p): " & Containing_Directory(P));
   Put_Line("Simple_Name(p): " & Simple_Name(P));

   -- We can check whether a path is absolute.
   Put_Line(Boolean'Image(Is_Absolute_Path("dir/file")));
   Put_Line(Boolean'Image(Is_Absolute_Path("/dir/file")));

   declare
      Filename : constant String := "config.json";
      Ext : constant String := Extension(Filename);
   begin
      -- Some file names have extensions following a dot.
      -- We can get the extension of such names with Extension.
      Put_Line(Ext);

      -- To find the file's name with the extension removed,
      -- use Ada.Strings.Fixed.Head.
      Put_Line(Head(Filename, Filename'Length - Ext'Length - 1));
   end;

   -- Ada.Directories doesn't have a direct equivalent to Rel.
   -- You would need to implement this functionality yourself if needed.

   -- Note: Error handling is omitted for brevity. In a real application,
   -- you should handle potential exceptions raised by these functions.
end File_Paths;

To run the program, save it as file_paths.adb and use your Ada compiler. For example, with GNAT:

$ gnatmake file_paths.adb
$ ./file_paths
p: dir1/dir2/filename
dir1/filename
dir1/filename
Containing_Directory(p): dir1/dir2
Simple_Name(p): filename
FALSE
TRUE
.json
config

Ada’s Ada.Directories package provides similar functionality to Go’s filepath package, but with some differences:

  1. Ada uses Compose instead of Join to construct paths.
  2. Ada’s Containing_Directory and Simple_Name are similar to Go’s Dir and Base.
  3. Ada doesn’t have a direct equivalent to Go’s Rel function for finding relative paths.
  4. Ada’s Extension function is similar to Go’s Ext.

Note that Ada’s path handling might behave differently on different operating systems, so always test your code on the target platform.