Skip to content

Provide a platform-agnostic way to determine the temp. directory, e.g., via an automatic variable. #4216

Closed

Description

Related: #3442 and #4215

The various supported platforms have different native ways to determine the directory in which to store temporary files and directories:

  • Windows:
    • $env:TEMP
  • macOS:
    • $env:TMPDIR
  • Linux:
    • /tmp

Currently, there is no platform-agnostic way to refer to this directory, which is cumbersome.

An automatic variable, say $TEMP, could provide this abstraction.

Environment data

PowerShell Core v6.0.0-beta.3

Activity

  1. lukeb1961 commented on Jul 11, 2017

    @lukeb1961

    what about something like: (New-TemporaryFile).DirectoryName

  2. mklement0 commented on Jul 11, 2017

    @mklement0
    ContributorAuthor

    lukeb1961: That indeed yields the platform-specific temporary directory, but it has an unwanted side effect: New-TemporaryFile invariably creates the file whose [System.IO.FileInfo] representation it outputs.

    In other words: every time you execute (New-TemporaryFile).DirectoryName, you leave an unused temporary file behind.

    Additionally, it's a computationally expensive approach.

  3. iSazonov commented on Jul 11, 2017

    @iSazonov
    Collaborator

    We've had discussed this in a nutshell. Thank you for opening the Issue.

    Internally we already have "TemporaryDirectory", just "GetTemporaryDirectory()" and "CreateTemporaryDirectory()". We could make it public.

  4. Liturgist commented on Jul 14, 2017

    @Liturgist

    How about going with $Env:TMP on all platforms? That is not quite like Windows, Mac, or Linux. No turf war.

  5. mklement0 commented on Jul 14, 2017

    @mklement0
    ContributorAuthor

    Liturgist: $Env:TMP is not an option, because it is ill-advised to either (a) have PowerShell automatically define environment variables or (b) pretend that non-existent environment variables exist.

    An automatic PowerShell variable such as $TMP is an option, however, although the thing to keep in mind is that retroactively introducing automatic variables is technically a breaking change.

  6. SteveL-MSFT commented on Jul 14, 2017

    @SteveL-MSFT
    Member

    If we went the variable route, it would have to be something like $interop:TEMP to avoid name collision. A variable is probably easier to use in scripts than an API although we can certainly support both.

    In #3571 I suggested other variables in addition to TEMP

  7. mklement0 commented on Jul 14, 2017

    @mklement0
    ContributorAuthor

    Steve Lee (@SteveL-MSFT):

    Good point; an $interop: namespace is indeed a way to avoid collisions.

    If we take a step back: If we want PowerShell to become the lingua franca of the shell world, do we really want to frame things as "interop"?

    How about trusting PowerShell's automatic variables to Do the Right Thing(TM) generically, which would call for a namespace such as $ps:?

  8. SteveL-MSFT commented on Jul 14, 2017

    @SteveL-MSFT
    Member

    Michael Klement (@mklement0) the $ps: prefix/namespace has been proposed before. It would be nice if we had used that from the beginning :)

    Personally, I prefer $ps: for exactly your reasoning. Perhaps this can be a discussion point at the next Community Call.

    cc @PowerShell/powershell-committee

  9. mklement0 commented on Jul 15, 2017

    @mklement0
    ContributorAuthor

    I'm glad to hear it, Steve Lee (@SteveL-MSFT).

    On a related note, I think a separate namespace for all preference variables would be beneficial as well, such as $pspref:

    The caveat is that even though collisions are far less likely than with unqualified variable names, someone could have done something like the following:

    # Define custom drive 'ps:'
    New-PSDrive 'ps' FileSystem '/tmp'; Get-ChildItem ps:
  10. iSazonov commented on Jul 15, 2017

    @iSazonov
    Collaborator
  11. mklement0 commented on Jul 15, 2017

    @mklement0
    ContributorAuthor

    Ilya (@iSazonov):

    That works, but it is both hard to remember and cumbersome to type.
    Good to know as a workaround, though.

  12. iSazonov commented on Jul 16, 2017

    @iSazonov
    Collaborator

    If we have New-TemporaryFile users expect Get-TemporaryPath of Get-TemporaryDirectory.

  13. mklement0 commented on Jul 16, 2017

    @mklement0
    ContributorAuthor

    Ilya (@iSazonov):

    Since the term path is ambiguous (even though it is used in the .NET API to refer to a directory path in this case), my preference would be Get-TemporaryDirectory, and I certainly wouldn't mind having such a cmdlet.

    That said, a cmdlet is a bit heavy-handed for something that returns a single piece of information with no variations in functionality.

    Consider the existing Get-Host / $Host duo: Do you ever find yourself using Get-Host instead of $Host?

  14. 49 remaining items

  15. Liturgist commented on Jan 19, 2019

    @Liturgist

    Thank you for curating the issues, Michael Klement.

    It seems that the tradition of a tmp/temp directory is that every program can us it in whatever way it wants. That works until name collision or there are multiple instances of the same program. In the first case, the applications must choose different names. In the second, the application may identify its files by including unique information such as its PID in the filename.

    (a) I fully agree that with guaranteed uniqueness, the application should not care about where a temporary file or directory is located or the name.

    A constraint should be that it is possible to locate post-mortem the temporary files and directories to enable anomaly remediation (finding and fixing bugs). Does this suggest that automatic temp cleanup should be a preference setting?

    The suggestion of -NamePrefix was based on an application being able to identify its own temprrary files in a single pool. Although guaranteed uniqueness obviates this as a requirement, the developer may find comfort in recognizing foo_xxxx.tmp, bar_xxxx.tmp, bosh_xxxx.tmp, and others when mutiple temporary files are in use.

    I agree that if we have New-TemporaryFile that we should have New-TemporaryDirectory.

  16. SteveL-MSFT commented on Jan 19, 2019

    @SteveL-MSFT
    Member

    Certainly TEMP: doesn't solve the unique temp folder that New-TemporaryDirectory would solve and the two are orthogonal. Uniqueness is certainly useful particularly if you have multiple processes or even runspaces, but that deviates from what this original issue intended.

  17. Liturgist commented on Jun 13, 2019

    @Liturgist

    What was the result of this discussion?

  18. SteveL-MSFT commented on Jun 14, 2019

    @SteveL-MSFT
    Member

    New-TemporaryDirectory is #3442

    A Temp: drive resolves this issue.

  19. Liturgist commented on Jun 15, 2019

    @Liturgist

    Steve Lee (@SteveL-MSFT) - Ok. I do not see a Temp: drive from Get-PSDrive in 6.2.1. Am I looking in the wrong place, or when might the Temp: drive become available? #3442 appears to show Waiting - DotNetCore.

    Will the Temp: drive be global for the system in the same way a /tmp on *NIX systems is currently?

    Will there be a New-TemporaryDirectory to be orthogonal with New-TemporaryFile?

  20. iSazonov commented on Jun 15, 2019

    @iSazonov
    Collaborator

    Liturgist It was an experimental feature. Now it is in 7.0. You can download daily build and find it there. It is "global" in PowerShell session.
    No immediate plans exist to implement New-TemporaryDirectory - you can discuss in #3442.

  21. SteveL-MSFT commented on Jun 20, 2019

    @SteveL-MSFT
    Member

    Liturgist if you want to try it on 6.2.1, just do this:

    Enable-ExperimentalFeature PSTempDrive

    Then restart pwsh.

  22. LYP951018 commented on Aug 1, 2019

    @LYP951018

    I'm trying TEMP:\ but I found that I could not use TEMP:\ directly in C# methods or external tools, e.g.

    [System.IO.Compression.ZipFile]::ExtractToDirectory($path, "TEMP:\foo")

    or

    unzip foo -d TEMP:\foo

    I must use Get-Item TEMP:\ or something to achieve this...

  23. mklement0 commented on Aug 1, 2019

    @mklement0
    ContributorAuthor

    Yupei Liu (@LYP951018):

    TEMP: is a PowerShell-only drive (you can list them with Get-PSDrive) and such drives aren't visible to the outside world, including .NET

    You must translate PS-drive-based paths to their underlying "native" filesystem paths, which is what Convert-Path is for.

    Note that there's another pitfall associated with passing filesystem paths to .NET methods (though not to external programs): .NET typically sees a different working directory than PowerShell, so that passing relative paths typically doesn't work as intended - it is best to pass full paths always, which Convert-Path can also help with.

    In short: it's good to form a habit of passing filesystem paths to .NET methods via
    Convert-Path -LiteralPath.

    If you stay in the realm of PowerShell, you won't face that problem; for instance, you could use Expand-Archive.

  24. anonhostpi commented on Nov 24, 2025

    @anonhostpi

    New-TemporaryDirectory is #3442

    A Temp: drive resolves this issue.

    New-TemporaryDirectory is being reconsidered: #25754 (comment)

    In that older issue, they chose to use dotnet APIs which was not adequate for CLM shells.

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

    Committee-ReviewedPS-Committee has reviewed this and made a decisionIssue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassifResolution-FixedThe issue is fixed.WG-Cmdletsgeneral cmdlet issues

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions