Getting home directory?

Andy picture Andy · Jun 15, 2017 · Viewed 15.4k times · Source

I'm trying to get a directory off of the user's home directory in a script. This is what I'm trying, but the ~ is interperated as a literal instead of expanding to the home directory. Is there anyway to get it to expand? If not, can I get the home directory another way?

$mySourceDir = "~/Projects/svn/myProject/trunk" # Single quote also does not expand
cd $mySourceDir

This is using the PS 6 beta on OSX.

Answer

mklement0 picture mklement0 · Jun 15, 2017

In PowerShell, the most robust way to refer to the current user's home directory is to use automatic variable $HOME, inside "..." if it is part of a larger path:

  • $mySourceDir = "$HOME/Projects/svn/myProject/trunk"; Set-Location $mySourceDir
    (Set-Location is PowerShell's cd equivalent; thanks to a built-in alias definition, you can use cd too, however.)

  • If you're passing a path as an argument to a command, you may be able to get away without the enclosing "...", depending on what characters the path contains; e.g.,
    Set-Location $HOME/Desktop

  • Works on both Windows and Unix platforms, whereas if you tried to use environment variables such as $env:HOME, platform differences would surface.

  • To learn about all automatic variables (built-in variables) that PowerShell defines, see the conceptual about_Automatic_Variables help topic (as of this writing, the description of $HOME reflects just the Windows perspective, but $HOME does work analogously on Unix platforms).


Use ~ only if you're certain that the current location is a filesystem location:

  • The current location is PowerShell's generalized concept of the current directory: PowerShell generalizes the concept of a drive to include other (typically) hierarchical data stores, such as the Windows registry, a directory of all defined functions (drive Function:), variables (Variable), or environment variables (Env:).

  • Each such drive is provided by a drive provider, of which the filesystem [drive provider] is just one instance.

  • ~ is a drive-provider-specific concept, so using just ~, without an explicit reference to a drive provider, refers to the home location as defined by the provider underlying the current location.

    • Some providers provide no default for what ~ represents, causing attempts to use it to fail; for instance, that is the case for the Environment drive provider and its Env: drive:
      Set-Location Env:; Set-Location ~ results in error
      Home location for this provider is not set. To set the home location, call "(get-psprovider 'Environment').Home = 'path'
  • It is the drive provider that interprets ~, so ~ also works inside '...' and "..."

    • From a filesystem location, the following commands all work the same:
      • Set-Location ~/Desktop
      • Set-Location "~/Desktop"
      • Set-Location '~/Desktop'
    • Contrast this with POSIX-like shells such as bash, where it is the shell that expands ~, up front, before the target command sees it, but only if it is unquoted.