Reputation: 1233
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?
Upvotes: 0
Views: 1384
Reputation: 175065
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)) "
}
Upvotes: 3