Skip to content

Unix utilities expect $env:PWD to reflect the current directory, as per POSIX #7388

Closed

Description

POSIX mandates the presence of an environment variable named PWD that should "represent an absolute pathname of the current working directory."

That is, POSIX-like shells keep the value of this env. variable in sync with their working dir. so that (non-shell) processes created from the shell can rely on it reflecting the shell's notion of the current dir.

PowerShell currently doesn't set this environment variable (it only sets its internal automatic $PWD variable, which other processes cannot see), which can have unintended consequences when invoking Unix utilities that rely on it.

This problem is conceptually related to #3428, for which there is no good solution due to its in-process nature.

In the case at hand, however, since a child process must be created to invoke an external program, it should be possible to add a PWD environment variable reflecting PowerShell's current filesystem location to the environment block of child processes spawned by PowerShell, on Unix-like platforms only.

Steps to reproduce (on macOS or Linux)

# Switch to an arbitrary location and make the Perl process display the value of $env:PWD
Set-Location /tmp; perl -le 'print $ENV{PWD}'  

Expected behavior

/tmp

That is, the external utility's process should see PowerShell's current filesystem location in its PWD environment variable.

(Note that using another shell (e.g., bash) for this test wouldn't be a valid test, because POSIX-like shells set the PWD environment variable themselves.)

Actual behavior

/home/jdoe     # e.g.

Even with PowerShell configured as the user's default shell, $env:PWD is still set at the time the PowerShell session starts, and seemingly always reflects the user's home dir.

Environment data

PowerShell Core v6.1.0-preview.4 on macOS 10.13.6
PowerShell Core v6.1.0-preview.4 on Ubuntu 16.04.4 LTS

Activity

  1. thezim commented on Jul 27, 2018

    @thezim
    Contributor

    Is there a goal to make PowerShell POSIX compliant?

  2. mklement0 commented on Jul 28, 2018

    @mklement0
    ContributorAuthor

    Greg Zimmerman (@thezim):

    It's not about POSIX compliance per se - it's just that POSIX-decreed functionality is, by and large, the common denominator across macOS and Linux - see #6518 (comment)

    If PowerShell wants to be a good cross-platform citizen and aspires to be the "universal shell" (which I hope it does), it must not contravene fundamental expectations of any platform's native utilities.

    Utilities (command-line programs) on Unix-like platforms may rely on environment variable ENV ($env:PWD, in PowerShell terms) reflecting the notion of the calling shell's current directory.

    PowerShell not respecting that can lead to subtle failures.

    If you want a specific example:

    After switching my default shell to PowerShell on macOS, my (standardized across projects) Makefiles started to break, because they try to add project-relative directories to $env:PATH, based on $env:PWD.

  3. added
    Issue-Enhancementthe issue is more of a feature request than a bug
    WG-Enginecore PowerShell engine, interpreter, and runtime
    on Jul 30, 2018
  4. iSazonov commented on Jul 30, 2018

    @iSazonov
    Collaborator

    I believe it will be easy-to-fix and good enhancement.

  5. Happycoil commented on Aug 21, 2019

    @Happycoil

    Just got bitten by this after changing my login shell to pwsh 7.0.0-preview.3. I expect lots of tools have code like this: https://github.com/chef/chef/blob/39cf0beb9ccc0fa0f60fa9d52b3c0a2bccc6c0f1/chef-config/lib/chef-config/workstation_config_loader.rb#L141-L149 and more people will be using pwsh as their login shell now...

    My particular issue can be solved by setting $env:PWD to an empty string, but I expect that'll break something else I haven't tried yet.

    GitHub
    A systems integration framework, built to bring the benefits of configuration management to your entire infrastructure. - chef/chef
  6. iSazonov commented on Aug 22, 2019

    @iSazonov
    Collaborator

    Code references:

    private Process Start(ProcessStartInfo startInfo)
    {
    Process process = null;
    if (startInfo.UseShellExecute)
    {
    process = StartWithShellExecute(startInfo);
    }
    else
    {
    #if UNIX
    process = new Process() { StartInfo = startInfo };
    SetupInputOutputRedirection(process);
    process.Start();
    if (process.StartInfo.RedirectStandardOutput)
    {
    process.BeginOutputReadLine();
    }
    if (process.StartInfo.RedirectStandardError)
    {
    process.BeginErrorReadLine();
    }
    if (process.StartInfo.RedirectStandardInput)
    {
    WriteToStandardInput(process);
    }
    #else
    process = StartWithCreateProcess(startInfo);
    #endif
    }
    return process;

    _nativeProcess = new Process() { StartInfo = startInfo };
    _nativeProcess.Start();

  7. rjmholt commented on Aug 20, 2020

    @rjmholt
    Collaborator

    It seems we could implement this with something like this property

  8. carschandler commented on Mar 7, 2024

    @carschandler

    Please re-open this. I believe the benefits far outweigh any cons, if there even are any. For example, I'm using a project with a Taskfile defined that assumes the PWD environment variable is set, which works for all platforms except Windows! Someone else already mentioned the same thing for Makefile. I'd imagine there are tons of build systems that have the same issue. We already have the automatic $PWD variable, so why not just expand this into a true environment variable? Just to explicitly not be POSIX compliant?

  9. kfsone commented on Aug 19, 2025

    @kfsone

    Tools like Helix's "p4" command rely on this as a way to track the difference between "my working directory" and "the shell environment's working directory".

    My work around has been:

    function Set-POSIXLocation { Set-Location @Args; $env:PWD = $PWD }
    function Push-POSIXLocation { Push-Location @Args; $env:PWD = $PWD }
    function Pop-POSIXLocation { Pop-Location @Args; $env:PWD = $PWD }
    New-Alias -Force -Option AllScope -Name cd -Value Set-POSIXLocation
    New-Alias -Force -Option AllScope -Name pushd -Value Push-POSIXLocation
    New-Alias -Force -Option AllScope -Name popd -Value Pop-POSIXLocation
    
  10. xtqqczze commented on Sep 25, 2025

    @xtqqczze
    Contributor

    Ilya (@iSazonov) Please reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Enhancementthe issue is more of a feature request than a bugResolution-No ActivityIssue has had no activity for 6 months or moreWG-Enginecore PowerShell engine, interpreter, and runtime

    Type

    No type

    Projects

    • Status
      Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions