--- name: chdir signature: 'chdir EXPR' signatures: - 'chdir EXPR' - 'chdir FILEHANDLE' - 'chdir DIRHANDLE' - 'chdir' since: 5.0 status: documented categories: ["Filehandles, files, directories"] --- ```{index} single: chdir; Perl built-in ``` *[Filehandles, files, directories](../perlfunc-by-category)* # chdir Change the process's current working directory. `chdir` is the Perl wrapper around the `chdir(2)` and — where the kernel supports it — `fchdir(2)` system calls. It changes the directory that relative paths are resolved against for the current process and, on success, persists that change for every subsequent file operation in the program. ## Synopsis ```perl chdir EXPR chdir FILEHANDLE chdir DIRHANDLE chdir ``` ## What you get back `1` on success, `0` on failure. On failure [`$!`](../perlvar) is set to the underlying `errno` so you can distinguish "no such directory" (`ENOENT`) from "permission denied" (`EACCES`) from "not a directory" (`ENOTDIR`): ```perl chdir $path or die "chdir $path failed: $!"; ``` The return is always a plain boolean — there is no separate "changed to nowhere because no argument was given" value. The no-argument form either succeeds by changing to the home directory or fails like any other call. ## Global state it touches - [`%ENV`](../perlvar) — read when `chdir` is called with no argument. The lookup order is `$ENV{HOME}` first, then `$ENV{LOGDIR}`. If neither is set, `chdir` does nothing and returns `0`. - [`$!`](../perlvar) — set on failure to the `errno` reported by the kernel. `chdir` does **not** update `$ENV{PWD}`. Shells maintain `PWD` themselves; a Perl program that cares about `PWD` for child processes has to assign to `$ENV{PWD}` after a successful `chdir`. ## Argument forms - **`chdir EXPR`** — `EXPR` is stringified and passed to `chdir(2)` as a pathname. Relative paths are resolved against the current working directory at the moment of the call. - **`chdir FILEHANDLE`** and **`chdir DIRHANDLE`** — on Linux (and any system with `fchdir(2)`) the kernel changes directory to the one the handle refers to. `FILEHANDLE` here means a filehandle opened on a directory, or a directory handle from [`opendir`](opendir). Using the handle form avoids a TOCTOU race between resolving a pathname and changing into it. - **`chdir`** (no argument) — changes to `$ENV{HOME}`, falling back to `$ENV{LOGDIR}` if `HOME` is unset. If both are unset the call fails and [`$!`](../perlvar) is left untouched; check the return value, not `$!`. ## Examples Change into a directory and bail out if it does not exist: ```perl chdir "/var/log" or die "cannot enter /var/log: $!"; ``` Run a block of work in a different directory and return to where you started: ```perl use Cwd qw(getcwd); my $origin = getcwd; chdir $work_dir or die "chdir $work_dir: $!"; # ... do work relative to $work_dir ... chdir $origin or die "chdir $origin: $!"; ``` Change via a directory handle (race-free on systems with `fchdir(2)`): ```perl opendir my $dh, $path or die "opendir $path: $!"; chdir $dh or die "fchdir $path: $!"; ``` Go home: ```perl chdir or die "no HOME/LOGDIR in environment"; ``` Probe a list of candidates, stopping at the first that works: ```perl for my $d ("/srv/app", "/opt/app", "/usr/local/app") { last if chdir $d; } ``` ## Edge cases - **Empty string or `undef`**: `chdir ""` and `chdir undef` both fail and set [`$!`](../perlvar) to `ENOENT`. They do **not** fall back to `$HOME` — the no-argument form is triggered by *absence* of an argument, not by an argument that happens to be empty. - **Relative paths on a thread with its own cwd**: the kernel's current working directory is per-process, not per-thread, on Linux. Two threads calling `chdir` concurrently race. - **Symlink to a directory**: `chdir` follows symlinks, landing in the target. Use [`readlink`](readlink) or [`Cwd::abs_path`](../../Cwd/abs_path) first if you need to know the real destination. - **Deleted directory**: if the directory was removed after you entered it, relative operations from inside fail with `ENOENT` and most shells show the path as `(deleted)`. You can still `chdir` out with an absolute path. - **Handle form on systems without `fchdir(2)`**: raises an exception. Linux always supports it; the restriction is a portability concern for code that also runs on older systems. - **Untrusted input**: passing a user-supplied path to `chdir` without validation lets the caller redirect all subsequent relative-path operations in the program. Canonicalise with [`Cwd::abs_path`](../../Cwd/abs_path) and check against an allow-list before the call if the input crosses a trust boundary. - **After [`fork`](fork)**: the child inherits the parent's cwd. A `chdir` in the child does not affect the parent. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`mkdir`](mkdir) — create a directory; pair with `chdir` when building a workspace and stepping into it - [`rmdir`](rmdir) — remove a directory; do not `rmdir` the cwd, `chdir` out first - [`opendir`](opendir) — open a directory handle usable as the argument to `chdir` for race-free directory changes - [`chroot`](chroot) — stronger confinement than `chdir`; changes the filesystem root for the process, not just the cwd - [`$ENV{HOME}`](../perlvar) — consulted by the no-argument form of `chdir` before falling back to `$ENV{LOGDIR}` - [`$!`](../perlvar) — carries the `errno` when `chdir` returns `0`