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

entries

self.entries

Opens the directory, collects every entry (via DirHandle's entries) into an Array, and closes it again. Returns nil if the directory couldn't be opened.

say Dir("/tmp").entries

files

self.files

Opens the directory, collects only its immediate regular-file entries (via DirHandle's files), and closes it. Unlike "find", this does not recurse into subdirectories.

subdirs

self.subdirs

Like "files", but collects only immediate subdirectory entries.

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")

size

self.size

Returns the total size, in bytes, of every regular file found recursively under this directory (via "walk").

say Dir("/var/log").size

walk

self.walk
self.walk(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.walk {|item|
    say(item) if item.is_file
}

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

Aliases: browse, find

each

self.each(block)

Opens the directory, calls block once per entry name (including . and ..), and closes it again. Returns true on success, false if the directory couldn't be opened.

Dir("/tmp").each {|name| say name }

glob

self.glob(pattern)

Returns an Array of every entry matching the shell glob pattern (e.g. "*.txt"), as File or Dir objects.

Dir("/var/log").glob("*.log").each {|f| say f }

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