NAME

Sidef::Types::Glob::DirHandle - Directory handle object for iterating and manipulating directories.

DESCRIPTION

This class implements a directory handle for reading and navigating directory contents in Sidef. A DirHandle provides an object-oriented interface to directory operations, allowing you to read entries, iterate through files, and manipulate the read position within a directory stream.

DirHandle objects are typically created by calling the open method on a Dir object, which opens the directory for reading and returns a DirHandle instance.

SYNOPSIS

# Open a directory and get a DirHandle
var dir = Dir('/path/to/directory')
var dh = dir.open

# Read entries one by one
while (var entry = dh.read) {
    say entry
}
dh.close

# Or iterate through raw entry names with a block
Dir('/path/to/directory').open.each { |name|
    say "Found: #{name}"
}

# Get all entries (as Dir/File objects) as an array
var entries = Dir('.').open.entries
say entries

INHERITS

Inherits methods from Sidef::Object::Object.

CONSTRUCTION

new

Sidef::Types::Glob::DirHandle.new(dh, dir)

Constructs a new DirHandle object that wraps a raw directory handle (as produced internally by opendir) together with the directory it belongs to. This is a low-level constructor: DirHandle objects are normally obtained by calling open on a Sidef::Types::Glob::Dir object rather than being built directly.

Aliases: call

DIRECTORY INFORMATION

dir

self.dir

Returns the directory this handle was opened from.

var dh = Dir('/home/user').open
var dir = dh.dir        # returns the associated Dir object
say dir                 # prints: /home/user

Aliases: parent

READING ENTRIES

read

self.read

Reads and returns the next entry from the directory as a Sidef::Types::Glob::Dir or Sidef::Types::Glob::File object, depending on the entry's type. Returns nil when there are no more entries. Each call advances the directory position to the next entry.

The special entries . and .. are automatically skipped, and symbolic links are silently ignored (they are not returned at all).

var dh = Dir('.').open

loop {
    var entry = dh.read
    entry || break
    say entry
}

dh.close

entries

self.entries

Returns an array containing all the entries in the directory, as Sidef::Types::Glob::Dir and Sidef::Types::Glob::File objects. Internally this rewinds the handle and then repeatedly calls read, so, like read, it excludes the . and .. entries as well as symbolic links.

var dh = Dir('/etc').open
var all_entries = dh.entries
say "Found #{all_entries.len} entries"
say all_entries

This is convenient when you need to work with all entries at once or want to apply array operations like sorting or filtering.

files

self.files

Returns an array containing only the regular files within the directory (i.e., the result of entries filtered down to entries where is_file is true). Subdirectories, symbolic links, and the . / .. entries are excluded.

var dh = Dir('.').open
var files = dh.files
files.each { |file|
    say "File: #{file}"
}

dirs

self.dirs

Returns an array containing only the subdirectories within the directory (i.e., the result of entries filtered down to entries where is_dir is true). Regular files, symbolic links, and the . / .. entries are excluded.

var dh = Dir('.').open
var subdirs = dh.dirs
subdirs.each { |subdir|
    say "Subdirectory: #{subdir}"
}

each

self.each(code)

Iterates through each raw entry in the directory, calling the provided code block once per entry with the entry's name as a plain string. Returns the DirHandle object.

Unlike read, entries, files, and dirs, this method reads directly from the underlying directory handle: it does not skip the . and .. entries, and it does not filter out symbolic links.

Dir('.').open.each { |name|
    say "Entry: #{name}"
}

iter

self.iter

Returns a callable iterator (a Block) that lazily yields the next raw entry name (as a string) each time it's invoked, returning nil once the directory is exhausted. This is useful for processing large directories without loading all entries into memory at once.

Like each, and unlike read, this reads directly from the underlying directory handle, so it does not skip the . and .. entries and does not filter out symbolic links.

var dh = Dir('.').open
var iterator = dh.iter

# Get entries one at a time
while (var entry = iterator.next) {
    say entry
}

POSITION CONTROL

tell

self.tell

Returns the current position within the directory stream as an integer. This position can be used later with seek to return to the same point in the directory.

var dh = Dir('.').open

dh.read  # read first entry
var pos = dh.tell  # get current position
say "Current position: #{pos}"

The position value is opaque and should only be used with seek on the same directory handle.

seek

self.seek(pos)

Sets the position within the directory stream to the specified position. The position value should be obtained from a previous tell call. Returns a boolean indicating success.

var dh = Dir('.').open

dh.read  # read first entry
var pos = dh.tell  # save position
dh.read  # read second entry
dh.read  # read third entry

dh.seek(pos)  # return to saved position
say dh.read   # reads second entry again

rewind

self.rewind

Resets the directory position back to the beginning, allowing you to read through the directory entries again from the start. This is useful when you need to make multiple passes through a directory.

var dh = Dir('.').open

# First pass
while (var entry = dh.read) {
    say "First pass: #{entry}"
}

# Reset to beginning
dh.rewind

# Second pass
while (var entry = dh.read) {
    say "Second pass: #{entry}"
}

dh.close

HANDLE MANAGEMENT

close

self.close

Closes the directory handle, releasing system resources. After closing, the DirHandle can no longer be used to read directory entries. Returns a boolean indicating success.

var dh = Dir('.').open
# ... read some entries ...
dh.close  # close the handle when done

It's good practice to close directory handles when you're finished with them, although Sidef will automatically close them when they go out of scope.

chdir

self.chdir

Changes the current working directory to the directory represented by this DirHandle. Returns a boolean indicating success or failure.

var dh = Dir('/tmp').open
dh.chdir  # changes current directory to /tmp
say Dir.cwd  # prints: /tmp

FILE STATUS

stat

self.stat

Returns a Sidef::Types::Glob::Stat object containing filesystem metadata about the directory represented by this handle.

var dh = Dir('.').open
var stat = dh.stat
say "Directory size: #{stat.size}"
say "Last modified: #{stat.mtime}"
say "Owner UID: #{stat.uid}"

lstat

self.lstat

Returns a Sidef::Types::Glob::Stat object containing filesystem metadata about the directory represented by this handle, following lstat semantics.

var dh = Dir('/tmp').open
var stat = dh.lstat
say "Directory inode: #{stat.ino}"
say "Permissions: #{stat.mode.as_oct}"

LOW-LEVEL ACCESS

get_value

self.get_value

Returns the raw underlying directory handle wrapped by this object. This is a low-level accessor, mainly intended for internal use or interoperability rather than everyday scripting.

EXAMPLES

Basic Directory Reading

# Read all files in the current directory
var dh = Dir('.').open
while (var file = dh.read) {
    say file
}
dh.close

Filtering Directory Contents

# Find all .txt files
Dir('.').open.each { |name|
    if (name ~~ /\.txt$/) {
        say "Text file: #{name}"
    }
}

Working with Subdirectories

# List all subdirectories
var dh = Dir('/home').open
var subdirs = dh.dirs
say "Subdirectories: #{subdirs.join(', ')}"

Recursive Directory Traversal

func traverse_dir(dir_path) {
    var dh = Dir(dir_path).open

    dh.each { |name|
        next if (name ~~ /^\.\.?$/)  # skip . and ..

        var full_path = Dir(dir_path) + name

        if (full_path.is_dir) {
            say "Directory: #{full_path}"
            traverse_dir(full_path)  # recurse
        } else {
            say "File: #{full_path}"
        }
    }

    dh.close
}

traverse_dir('/path/to/start')

Using Iterator for Large Directories

# Process large directory lazily
var iter = Dir('/var/log').open.iter

while (var entry = iter.next) {
    if (entry ~~ /\.log$/) {
        say "Log file: #{entry}"
    }
}

SEE ALSO

Sidef::Types::Glob::Dir, Sidef::Types::Glob::File, Sidef::Types::Glob::FileHandle, Sidef::Types::Glob::Stat

NOTES

The order in which directory entries are returned is not guaranteed and may vary depending on the underlying filesystem. If you need sorted entries, use the entries method and sort the resulting array.

read, entries, files, and dirs all skip the special . and .. entries and silently ignore symbolic links. In contrast, each and iter read directly from the underlying directory handle and include ., .., and symbolic links, returning plain entry-name strings rather than Dir/File objects.