0

The question seems pretty easy, the method I used below should work but it doesn't:

PS C:\Users\John.Smith\Downloads> rm .\uucode.ps1
PS C:\Users\John.Smith\Downloads> [System.IO.File]::Exists("uucode.ps1")
True
PS C:\Users\John.Smith\Downloads> [System.IO.File]::Exists(".\uucode.ps1")
True

I deleted the file, but it still indicates the file exists. I figured out that it is looking for the file under my home directory (even when "." is specified):

PS C:\Users\John.Smith\Downloads> rm ..\uucode.ps1
PS C:\Users\John.Smith\Downloads> [System.IO.File]::Exists("uucode.ps1")
False
PS C:\Users\John.Smith\Downloads> [System.IO.File]::Exists(".\uucode.ps1")
False

Is this a bug or something? The OS and Powershell version I am using are:

PS C:\Users\John.Smith\Downloads> (Get-WmiObject -class Win32_OperatingSystem).Caption
Microsoft Windows Server 2012 R2 Standard

PS C:\Users\John.Smith\Downloads> $psversiontable.psversion
Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      14409  1005

One solution I can think of myself is to find the current directory using pwd, and check if the file supplied to me is if a relative path (not starting with \ or /), and join the current directory with the relative path, but I think there should be an easier way, can you help me?

1

1 Answer 1

3

Is this a bug or something?

No, this behavior is expected.

.NET methods that take relative paths as arguments will resolve them relative to the working directory of the calling process - and powershell.exe doesn't update its current working directory when you navigate between locations inside PowerShell itself:

PS C:\Users\John.Smith> [System.Environment]::CurrentDirectory
C:\Users\John.Smith
PS C:\Users\John.Smith> cd Downloads
PS C:\Users\John.Smith\Downloads> [System.Environment]::CurrentDirectory
C:\Users\John.Smith

You can solve it by only passing rooted file system paths:

PS C:\Users\John.Smith\Downloads> [System.IO.File]::Exists("$PWD\uucode.ps1")
PS C:\Users\John.Smith\Downloads> [System.IO.File]::Exists('C:\Users\John.Smith\Downloads\uucode.ps1')

... or, preferably, just stick to PowerShell's provider cmdlets - when in a FileSystem location, Test-Path -PathType Leaf would be the equivalent of [File]::Exists():

PS C:\Users\John.Smith\Downloads> Test-Path .\uucode.ps1 -PathType Leaf # always correctly resolves path relative to $PWD

If you want PowerShell to always update the current working directory of the host application process, you could do so in the prompt function

$function:prompt = {
  # Need to check that we're in the file system - can't set process directory to a registry path for example
  if ($PWD.Provider.Name -eq 'FileSystem') {
    [System.IO.Directory]::SetCurrentDirectory($PWD)
  }
  return "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) "
}
Sign up to request clarification or add additional context in comments.

2 Comments

@mathias-r-jessen Thanks a lot for answering my question. I tested Test-Path and it worked with both absolute and relative path without using -PathType. Is there anything that I should be concerned, or I will mark the question answered.
Great, you're welcome! Beware that Test-Path .\uucode.ps1 will also return $true for directories (or junctions), so if you expect uucode.ps1 to not just exists, but specifically be a file, then I'd suggest keeping -PathType Leaf

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.