NAME

Sidef::Types::Glob::Dir - Directory manipulation and navigation in Sidef

DESCRIPTION

The Dir class provides directory manipulation capabilities in Sidef: creation, deletion, navigation, and traversal of directory structures. It's a subclass of Sidef::Types::Glob::File, so every method documented in Sidef::Types::Glob::File is also available on a Dir object -- though a few of them (read, write, size, and so on) don't really make sense for a directory even though they're technically callable.

Paths are decoded/encoded as UTF-8 where the underlying Perl core modules require it.

SYNOPSIS

# Create a Dir object
var dir = Dir("/path/to/directory")
var home = Dir.home
var temp = Dir.tmp

# Directory creation
dir.create                  # Create a single directory
dir.create_tree             # Create a directory with any needed parents

# Directory navigation
Dir.cwd                     # Get the current working directory
dir.chdir                   # Change to this directory
dir.parent                  # Get the logical parent directory
dir.up                      # Append ".." (unresolved)

# Directory operations
dir.is_empty                # Check if the directory is empty
dir.remove                  # Remove an empty directory
dir.remove_tree             # Recursively remove a directory and its contents

# Directory traversal
dir.find {|item|
    say(item)               # Iterate over the directory and everything below it
}

# Path manipulation -- '+' only returns a File if given an actual File object!
var subdir = (dir + "subdir")          # a Dir, even though it looks like a name
var file   = (dir + File("file.txt"))  # a File, because the argument already is one
var parts  = dir.split                 # Split the path into components

INHERITS

Inherits methods from Sidef::Types::Glob::File.

CONSTRUCTION

new

Dir(path)
Dir(*path_components)
Dir.new(path)

Creates a new Dir object. With a single string argument, path is used as-is. With more than one argument, the arguments are joined as path components (via File::Spec::catdir) into a single path. With a single argument that's any kind of reference (a File, another Dir, or anything else), this instead delegates entirely to calling .to_dir on it and returns that result -- so the given object's own class must actually provide a working to_dir method.

var dir1 = Dir("/home/user")
var dir2 = Dir("home", "user", "documents")
var dir3 = Dir(some_file_obj)      # delegates to some_file_obj.to_dir

Aliases: call

SPECIAL DIRECTORIES

root

Dir.root

Returns a Dir representing the filesystem's root directory ("/" on Unix-like systems).

say(Dir.root)   #=> Dir("/")

home

Dir.home

Returns a Dir representing the current user's home directory, determined (in order) from the HOME or LOGDIR environment variables, a system user-database lookup (on non-Windows systems), or File::HomeDir as a last resort.

say(Dir.home)   # e.g. Dir("/home/username")

tmp

Dir.tmp

Returns a Dir representing the system's temporary directory.

say(Dir.tmp)   # e.g. Dir("/tmp")

Aliases: temp

cwd

Dir.cwd

Returns a Dir representing the current working directory, as an absolute, resolved path.

say(Dir.cwd)

pwd

Dir.pwd

Returns a Dir representing the current directory as the literal, unresolved string "." -- unlike "cwd", this is not turned into an absolute path.

say(Dir.pwd)   #=> Dir(".")

mktemp

Dir.mktemp(%options)

Creates a new, empty temporary directory (via File::Temp::tempdir) and returns a Dir for it. It's automatically removed when the program exits (CLEANUP is always enabled). %options are forwarded to File::Temp::tempdir.

var tmpdir = Dir.mktemp
tmpdir.chdir

Aliases: make_tmp, make_temp

PATH MANIPULATION

concat

self.concat(other)
self + other

If other is specifically a File object (not a Dir, and not a plain string, even one that looks like a filename), joins the paths with File::Spec::catfile and returns a File. For anything else -- including a plain string like "file.txt", or a Dir -- joins the paths with File::Spec::catdir instead and returns a Dir. In other words, the only way to get a File back from + is to pass an actual File object; a bare string argument always produces a Dir, regardless of what it looks like.

var home = Dir.home

say(home + "Documents")         #=> Dir(".../Documents")
say(home + "file.txt")          #=> Dir(".../file.txt") -- still a Dir!
say(home + File("file.txt"))    #=> File(".../file.txt") -- a File, because the argument was one

Aliases: operator +, catfile

split

self.split

Splits the directory path into its components, via File::Spec::splitdir, and returns them as an Array of Strings.

say(Dir("/home/user/documents").split)   #=> ["", "home", "user", "documents"]

parent

self.parent

Returns a Dir for the logical parent directory, computed textually (via File::Basename::dirname) rather than by consulting the filesystem. Compare with "up", which doesn't compute anything -- it just appends a literal "..".

say(Dir("/home/user/documents").parent)   #=> Dir("/home/user")

up

self.up
Dir.up

Returns a new Dir with a literal ".." appended to the path (via File::Spec, so the platform's own separator is used) -- unlike "parent", nothing is resolved or simplified. Called on the Dir class itself (with no instance), returns just Dir("..") on its own, unanchored to any particular directory.

say(Dir("/home/user/documents").up)   #=> Dir("/home/user/documents/..")
say(Dir.up)                           #=> Dir("..")

get_value

self.get_value

Returns the raw underlying path string (unwrapped from the Dir object). A low-level method, mainly useful for interop rather than everyday Sidef code.

to_dir

self.to_dir

Returns self unchanged (a Dir is already a directory).

to_str

self.to_str

Returns the directory's path as a plain String.

say(Dir("/home/user").to_str)   #=> "/home/user"

Aliases: to_s

dump

self.dump

Returns a String representation of the Dir object for debugging, in the format Dir("path").

say(Dir("/tmp").dump)   #=> Dir("/tmp")

NAVIGATION

chdir

self.chdir

Changes the process's current working directory to this one. Returns true on success, false otherwise. This is process-wide, not local to any particular scope.

Dir("/tmp").chdir

chroot

self.chroot

Changes the process's root directory to this one (typically requires superuser privileges). Returns true on success, false otherwise. Like "chdir", this affects the entire process.

Dir("/jail").chroot

CREATING AND REMOVING

create

self.create

Creates the directory. Its immediate parent must already exist -- for creating any missing parent directories too, see "create_tree". Returns true on success, false otherwise.

Dir("newdir").create

Aliases: make, mkdir

create_tree

self.create_tree

Creates the directory, along with any missing parent directories (like mkdir -p). Returns true if the directory already existed or was successfully created, false otherwise.

Dir("/path/to/deep/nested/dir").create_tree

Aliases: make_tree, mktree, make_path, mkpath

remove

self.remove

Removes the directory. It must be empty -- for removing a directory and everything inside it, see "remove_tree". Returns true on success, false otherwise.

Dir("empty_dir").remove

Aliases: delete, unlink

remove_tree

self.remove_tree

Recursively removes the directory and everything inside it. This cannot be undone. Returns true on success, false otherwise.

Dir("old_project").remove_tree

CONTENTS AND TRAVERSAL

is_empty

self.is_empty

Returns true if the directory contains no entries (other than . and ..), false if it has any, or nil if the directory can't be opened at all.

Dir("test").is_empty && say("Directory is empty")

find

self.find
self.find(block)

Recursively traverses the directory tree, starting from (and including) the directory itself. With a block, calls it once for every item found (a Dir for each subdirectory, a File for each regular file) and returns self. With no block, collects everything into an Array instead.

dir.find {|item|
    say(item) if item.is_file
}

var all_items = dir.find
say("Found #{all_items.len} items")

Aliases: browse

open

self.open
self.open(fh_ref, err_ref=nil)

Opens the directory for reading its entries. With no arguments, returns a DirHandle on success, or nil on failure. With fh_ref, stores the handle through it and returns true/false instead (storing any error message through err_ref, if given).

var dh = Dir("/tmp").open
dh.each {|entry| say(entry) }

Aliases: open_r

open_w

self.open_w

Not implemented. Calling this currently raises a runtime "Unimplemented" error -- it's a placeholder for future write-mode directory support, not a harmless no-op.

open_rw

self.open_rw

Not implemented. Like "open_w", calling this currently raises a runtime "Unimplemented" error.

EXAMPLES

Basic directory operations

var project = Dir("my_project")
project.create_tree
project.chdir

var src = (project + "src")   # a Dir, since a plain string always produces one
var lib = (project + "lib")
src.create
lib.create

Directory traversal

var docs = Dir("documents")

# find() includes the starting directory itself in the traversal
docs.find {|item|
    if (item.is_file && item.match(/\.txt$/)) {
        say(item)
    }
}

var all = docs.find
say("Total items: #{all.len}")

Temporary directories

var tmpdir = Dir.mktemp
say("Using temp directory: #{tmpdir}")

tmpdir.chdir
# ... work happens here ...
# tmpdir is automatically removed when the program exits

Cleaning up

var old = Dir("obsolete")
old.is_empty && old.remove

var cache = Dir(".cache")
cache.remove_tree   # removes everything, recursively

Getting a File, not a Dir, from concatenation

var home = Dir.home

var maybe_dir = (home + "notes.txt")           # still a Dir -- plain strings never become Files
var actually_file = (home + File("notes.txt")) # a File, since the argument was one

SEE ALSO

Sidef::Types::Glob::File, Sidef::Types::Glob::DirHandle