Working With Directories

  • Revision slug: FileGuide/Directories
  • Revision title: Working With Directories
  • Revision id: 98987
  • Created:
  • Creator: trevorh
  • Is current revision? No
  • Comment Update to use templates; 136 words added, 34 words removed

Revision Content

Working With Directories

A reference to a directory may be created in the same way as with a file by using {{ ifmethod("nsIScriptableIO","getFile") }}. You can access a subdirectory by supplying a directory name as the second argument, or refer to one of the special directories by supplying a null string for the second argument. The first line below with retrieve the directory corresponding to the user's home directory, while the second will retrieve the directory 'myfiles' on the desktop.

var dir1 = IO.getFile("Home", "");
var dir2 = IO.getFile("Desktop", "myfiles");

To refer to a subdirectory, rather than using a path, use {{ ifmethod("nsIFile","append") }} to build up a path. For instance:

var dir2 = IO.getFile("Desktop", "myfiles");
dir2.append("pictures");
dir2.append("vacations");

In this example, a subdirectory several levels down is referenced. Each call to {{ ifmethod("nsIFile","append") }} navigates to a further subdirectory. The result is a subdirectory three levels below the desktop directory. These directories do not need to exist yet, but they can be created using {{ ifmethod("nsIFile","create") }}. See Creating Directories below for information about this. Note that {{ ifmethod("nsIFile","append") }} modifies the file object, rather than returning a new one.

Both files and directories are represented using the same kind of object so most of the functions available for {{ interface("nsIFile") }} will work for both. You can check if the object refers to a directory or a file by using {{ ifmethod("nsIFile","isDirectory") }}. This method returns true if a file object returned by {{ ifmethod("nsIScriptableIO","getFile") }} refers to a directory, and false otherwise. There is also a corresponding {{ ifmethod("nsIFile","isFile") }} method to check if an object refers to a file. In both cases, the method fails if the file or directory does not exist, so you should check first using {{ ifmethod("nsIFile","exists") }}.

var dir = IO.getFile("Desktop", "myfiles");
dir.append("pictures");
if (dir.exists() && dir.isDirectory())
  alert("This is a directory");

Creating Directories

You can create a new directory by using {{ ifmethod("nsIFile","create") }}. For directories, the first argument to this method should be the constant DIRECTORY_TYPE (which has a value of 1). To create a file instead, you could use the constant NORMAL_FILE_TYPE instead.

var dir = IO.getFile("Desktop", "myfiles");
dir.append("pictures");
if (!dir.exists())
  dir.create(dir.DIRECTORY_TYPE, 0775);

This example checks if the directory exists and creates it if it does not. If the directory already exists, then no action is taken. In this case, the directory is the 'pictures' subdirectory within the 'myfiles' directory on the desktop. If either the 'myfiles' directory or the 'pictures' directory do not exist, they will be created. Thus, you do not have to create a series of directories individually, the set will all be created if needed. Naturally, if the 'myfiles' directory already exists, it won't be recreated.

Iterating over the Files in a Directory

The directory object's directoryEntries ({{ interfaceattribute("nsIFile","Attributes") }}) attribute is used to get a list of the items in a directory. It returns an enumeration which can be iterated over.

function getLatestFile()
{
  var lastmod = 0;
  var homedir = IO.getFile("Home", "");
  var items = homedir.directoryEntries;
  while (items.hasMoreElements()) {
    var item = items.getNext().QueryInterface(Components.interfaces.nsIFile);
    if (item.isFile() && item.lastModifiedTime > lastmod.lastModifiedTime)
      lastmod = item;
  }

  return lastmod;
}

This example iterates through the files in the Home directory and looks for the file with the latest modification time (the last file in that directory that was written to). As the directoryEntries ({{ interfaceattribute("nsIFile","Attributes") }}) property is an enumeration, you can iterate over the items by using {{ ifmethod("nsISimpleEnumerator","hasMoreElements") }} and {{ ifmethod("nsISimpleEnumerator","getNext") }}. For each item, {{ ifmethod("nsIFile","isFile") }} is called to check if an item is a file and lastModifiedTime ({{ interfaceattribute("nsIFile","Attributes") }}) attribute is compared with the time of the lastmod reference. If the time is higher, the lastmod variable is updated as needed. The result is that lastmod will be set to the file with the latest modification time. {{ ifmethod("nsIFile","isFile") }} is used to ensure that the modification times are only examined for files, and not subdirectories.

But you could iterate over subdirectories as well. The following example returns an array of all of a directory's subdirectories:

function getSubdirs()
{
  var arr = [];
  var items = IO.getFile("Home", "").directoryEntries;
  while (items.hasMoreElements()) {
    var item = items.getNext();
    if (item.isDirectory())
      arr.push(item);
  }

  return arr;
}

Revision Source

<h3 name="Working_With_Directories">Working With Directories</h3>
<p>A reference to a directory may be created in the same way as with a file by using {{ ifmethod("nsIScriptableIO","getFile") }}. You can access a subdirectory by supplying a directory name as the second argument, or refer to one of the special directories by supplying a null string for the second argument. The first line below with retrieve the directory corresponding to the user's home directory, while the second will retrieve the directory 'myfiles' on the desktop.</p>
<pre class="brush: js">var dir1 = IO.getFile("Home", "");
var dir2 = IO.getFile("Desktop", "myfiles");
</pre>
<p>To refer to a subdirectory, rather than using a path, use {{ ifmethod("nsIFile","append") }} to build up a path. For instance:</p>
<pre class="brush: js">var dir2 = IO.getFile("Desktop", "myfiles");
dir2.append("pictures");
dir2.append("vacations");
</pre>
<p>In this example, a subdirectory several levels down is referenced. Each call to {{ ifmethod("nsIFile","append") }} navigates to a further subdirectory. The result is a subdirectory three levels below the desktop directory. These directories do not need to exist yet, but they can be created using {{ ifmethod("nsIFile","create") }}. See <a href="#Creating_Directories">Creating Directories</a> below for information about this. Note that {{ ifmethod("nsIFile","append") }} modifies the file object, rather than returning a new one.</p>
<p>Both files and directories are represented using the same kind of object so most of the functions available for {{ interface("nsIFile") }} will work for both. You can check if the object refers to a directory or a file by using {{ ifmethod("nsIFile","isDirectory") }}. This method returns true if a file object returned by {{ ifmethod("nsIScriptableIO","getFile") }} refers to a directory, and false otherwise. There is also a corresponding {{ ifmethod("nsIFile","isFile") }} method to check if an object refers to a file. In both cases, the method fails if the file or directory does not exist, so you should check first using {{ ifmethod("nsIFile","exists") }}.</p>
<pre class="brush: js">var dir = IO.getFile("Desktop", "myfiles");
dir.append("pictures");
if (dir.exists() &amp;&amp; dir.isDirectory())
  alert("This is a directory");
</pre>
<h4 name="Creating_Directories">Creating Directories</h4>
<p>You can create a new directory by using {{ ifmethod("nsIFile","create") }}. For directories, the first argument to this method should be the constant <code>DIRECTORY_TYPE</code> (which has a value of 1). To create a file instead, you could use the constant <code>NORMAL_FILE_TYPE</code> instead.</p>
<pre class="brush: js">var dir = IO.getFile("Desktop", "myfiles");
dir.append("pictures");
if (!dir.exists())
  dir.create(dir.DIRECTORY_TYPE, 0775);
</pre>
<p>This example checks if the directory exists and creates it if it does not. If the directory already exists, then no action is taken. In this case, the directory is the 'pictures' subdirectory within the 'myfiles' directory on the desktop. If either the 'myfiles' directory or the 'pictures' directory do not exist, they will be created. Thus, you do not have to create a series of directories individually, the set will all be created if needed. Naturally, if the 'myfiles' directory already exists, it won't be recreated.</p>
<h4 name="Iterating_over_the_Files_in_a_Directory">Iterating over the Files in a Directory</h4>
<p>The directory object's <code>directoryEntries</code> ({{ interfaceattribute("nsIFile","Attributes") }}) attribute is used to get a list of the items in a directory. It returns an enumeration which can be iterated over.</p>
<pre class="brush: js">function getLatestFile()
{
  var lastmod = 0;
  var homedir = IO.getFile("Home", "");
  var items = homedir.directoryEntries;
  while (items.hasMoreElements()) {
    var item = items.getNext().QueryInterface(Components.interfaces.nsIFile);
    if (item.isFile() &amp;&amp; item.lastModifiedTime &gt; lastmod.lastModifiedTime)
      lastmod = item;
  }

  return lastmod;
}
</pre>
<p>This example iterates through the files in the Home directory and looks for the file with the latest modification time (the last file in that directory that was written to). As the <code>directoryEntries</code> ({{ interfaceattribute("nsIFile","Attributes") }}) property is an enumeration, you can iterate over the items by using {{ ifmethod("nsISimpleEnumerator","hasMoreElements") }} and {{ ifmethod("nsISimpleEnumerator","getNext") }}. For each item, {{ ifmethod("nsIFile","isFile") }} is called to check if an item is a file and <code>lastModifiedTime</code> ({{ interfaceattribute("nsIFile","Attributes") }}) attribute is compared with the time of the <code>lastmod</code> reference. If the time is higher, the <code>lastmod</code> variable is updated as needed. The result is that <code>lastmod</code> will be set to the file with the latest modification time. {{ ifmethod("nsIFile","isFile") }} is used to ensure that the modification times are only examined for files, and not subdirectories.</p>
<p>But you could iterate over subdirectories as well. The following example returns an array of all of a directory's subdirectories:</p>
<pre class="brush: js">function getSubdirs()
{
  var arr = [];
  var items = IO.getFile("Home", "").directoryEntries;
  while (items.hasMoreElements()) {
    var item = items.getNext();
    if (item.isDirectory())
      arr.push(item);
  }

  return arr;
}
</pre>
Revert to this revision