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?

TylerH
  • 20,799
  • 66
  • 75
  • 101
puravidaso
  • 1,013
  • 1
  • 5
  • 22
  • Does this answer your question? https://stackoverflow.com/questions/11246068/why-dont-net-objects-in-powershell-use-the-current-directory – Doug Maurer Sep 16 '20 at 18:04

1 Answers1

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)) "
}
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • @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. – puravidaso Sep 16 '20 at 18:43
  • 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` – Mathias R. Jessen Sep 16 '20 at 18:45