In Windows shell you can fetch the contents of a file and copy it to "\Device\Null" with a command like copy c:\filename NUL. (This is useful for recalling externally-archived files without wasting space or updating with touch.)
But I can't figure out how to do the same in PowerShell using $null, NUL, \\.\NUL and more (and I don't want to call out a separate CMD.EXE process to do this for every file).
PS C:\> Copy-Item -Path .\filename -Destination NUL
Copy-Item : Cannot process path 'C:\NUL' because the the target represents a reserved device name.
At line:1 char:10
+ Copy-Item <<<< -Path .\filename -Destination NUL
+ CategoryInfo : WriteError: (C:\NUL:String) [Copy-Item], IOException
+ FullyQualifiedErrorId : CopyError,Microsoft.PowerShell.Commands.CopyItemCommand
PS C:\> Copy-Item .\filename NUL
Copy-Item : Cannot process path 'C:\NUL' because the the target represents a reserved device name.
At line:1 char:10
+ Copy-Item <<<< .\filename NUL
+ CategoryInfo : WriteError: (C:\NUL:String) [Copy-Item], IOException
+ FullyQualifiedErrorId : CopyError,Microsoft.PowerShell.Commands.CopyItemCommand
PS C:\> copy .\filename '\\.\NUL'
Copy-Item : Cannot process path '\\.\NUL' because the the target represents a reserved device name.
At line:1 char:5
+ copy <<<< .\filename '\\.\NUL'
+ CategoryInfo : WriteError: (\\.\NUL:String) [Copy-Item], IOException
+ FullyQualifiedErrorId : CopyError,Microsoft.PowerShell.Commands.CopyItemCommand
Any other ideas how to do this?
Effectively, you just want to do a read on the file. If so, this will work:
Get-ChildItem .\filename | Get-Content | Out-Null
It's probably overkill though. You could try:
$File=[system.io.file]::OpenRead(".\filename")
$File.Close()
This just opens the file for reading (which may be enough to bring it back) and closes it again.
Related
Suppose I cd to an empty directory in powershell and run the following command:
get-childitem x
The command will throw an error that it cannot find the path, which is expected.
However, when I check the $LastExitCode it is still zero.
This is confusing to me, since according to the docs $LastExitCode should contain the exit code of the last windows-based program that was run.
Could anyone please explain why the exit code is still zero after I run a command which clearly fails?
get-childitem doesn't start a new process. If a powershell function or command throws an error it will be stored in the global $Error array. $LASTEXITCODE is created and set when you start a child process, for example a new powershell session with a command:
PS C:\> Get-ChildItem x
Get-ChildItem : Cannot find path 'C:\x' because it does not exist.
At line:1 char:1
+ Get-ChildItem x
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\x:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
PS C:\> $Error.Count
1
PS C:\> $Error[0]
Get-ChildItem : Cannot find path 'C:\x' because it does not exist.
At line:1 char:1
+ Get-ChildItem x
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\x:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
PS C:\> $LASTEXITCODE
PS C:\> powershell -Command { get-childitem x }
get-childitem : Cannot find path 'C:\x' because it does not exist.
At line:1 char:2
+ get-childitem x
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\x:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
PS C:\> $LASTEXITCODE
1
PS C:\> powershell -Command { get-childitem . }
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
.....
.....
.....
PS C:\> $LASTEXITCODE
0
PS C:\>
In a powershell script you can do something like this at the bottom:
exit $error.count
Then the exit code will be the number of errors.
Total newbie here...
I am attempting to execute a ps1 file using Powershell and receiving an error. What does this error mean? I'm concerned that OneDrive is causing an issue with the path.
Running this ps1 file by opening powershell and entering:
PowerShell -executionpolicy Bypass -NoExit C:\Users\Terry\OneDrive\desktop\WindowsPull.ps1
This is the file:
$segmentFolders = Get-ChildItem | where {$_.Attributes -eq 'Directory'}
Error:
Set-Location : Cannot process argument because the value of argument "path" is null. Change the value of argument
"path" to a non-null value.
At C:\Users\Terry\OneDrive\desktop\WindowsPull.ps1:4 char:1
+ Set-Location $videoDir.FullName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Location], PSArgumentNullException
+ FullyQualifiedErrorId : ArgumentNull,Microsoft.PowerShell.Commands.SetLocationCommand
Can someone please explain the following behaviour to me?
PS C:\Users\Kenny> $filePath = "C:\\Complicated.File.Path.That.Has.Special-Chars`[but-no.spaces`]and.definitely.exists\"
PS C:\Users\Kenny> cd $filePath
cd : Cannot find path 'C:\\Complicated.File.Path.That.Has.Special-Chars[but-no.spaces]and.definitely.exists\' because it does not exist.
At line:1 char:1
+ cd $filePath
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\\Complicated...initely.exists\:String) [Set-Location], ItemNotFoundE
xception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
PS C:\Users\Kenny> cd 'C:\\Complicated.File.Path.That.Has.Special-Chars`[but-no.spaces`]and.definitely.exists\'
PS C:\Complicated.File.Path.That.Has.Special-Chars[but-no.spaces]and.definitely.exists> cd c:
PS C:\Users\Kenny> Write-Host $filePath
C:\\Complicated.File.Path.That.Has.Special-Chars[but-no.spaces]and.definitely.exists\
PS C:\Users\Kenny> cd "$filePath"
cd : Cannot find path 'C:\\Complicated.File.Path.That.Has.Special-Chars[but-no.spaces]and.definitely.exists\' because it does not exist.
At line:1 char:1
+ cd "$filePath"
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\\Complicated...initely.exists\:String) [Set-Location], ItemNotFoundE
xception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
PS C:\Users\Kenny> cd ${filePath}
cd : Cannot find path 'C:\\Complicated.File.Path.That.Has.Special-Chars[but-no.spaces]and.definitely.exists\' because it does not exist.
At line:1 char:1
+ cd ${originalPath}
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\\Complicated...initely.exists\:String) [Set-Location], ItemNotFoundE
xception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
PS C:\Users\Kenny> cd ${$filePath}
cd : Cannot process argument because the value of argument "path" is null. Change the value of argument "path" to a
non-null value.
At line:1 char:1
+ cd ${$filePath}
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Location], PSArgumentNullException
+ FullyQualifiedErrorId : ArgumentNull,Microsoft.PowerShell.Commands.SetLocationCommand
PS C:\Users\Kenny> cd $($filePath)
cd : Cannot find path 'C:\\Complicated.File.Path.That.Has.Special-Chars[but-no.spaces]and.definitely.exists\' because it does not exist.
At line:1 char:1
+ cd $($filePath)
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\\Complicated...initely.exists\:String) [Set-Location], ItemNotFoundE
xception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
If I had a penny for every minute I've wasted on PowerShell's insistance that backticks, quotes and other meta-characters are just right, I would be the richest man on Earth! Somebody please save me from this madness!
And BTW, what I'm actually trying to do is recurse through a bunch of folders and delete everything that isn't a video file, like so...
Remove-Item -Path $filePath -Recurse -Exclude '*.avi','*.mkv','*.mp4'
...which doesn't work for (presumably) the same reason: not being able to pass a variable to the -Path parameter. And if someone is feeling really generous, they could also help me with this. MTIA! :D
Use -LiteralPath instead of -Path because some of the special characters where interpreted with -Path.
Remove-Item -LiteralPath
Special characters are just so much fun in PS right?
-LiteralPath works exactly like Patrick explained, but they don't allow for wildcards; because they're literal.
Have you tried using single quotes ' instead of double quotes ". This allows you to escape special characters, while still evaluating wildcards. Try the commands below:
New-Item -Path 'C:\Users\username\PSScripts\bracket`[\te$t.txt'
Get-Item -Path 'C:\Users\username\PSScripts\bracket`[\*'
Also, if it helps, I use VSCode for most scripting and, if you use tab completion, it will format this properly for you.
I hope that helps!
The solution to my overall problem ended up being this line of my batch script:
powershell -Command "Get-ChildItem -Recurse -LiteralPath %filePath% | Where-Object Extension -match '^(?!(\.avi|\.mkv|\.mp4)$)' | Remove-Item"
The regex was the hardest to get right, since I haven't used negative lookaheads before, but after ~2 hours of total time spent on this one line of code, it finally works!
I found a way to get the current working directory into $dp0.
PS C:\src\powershell> Get-Content .\curdir2.ps1
$dp0 = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition)
Set-Location -Path $dp0
Write-Host "location is set"
Set-Location -Path [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition)
Write-Host (Get-Location).Path
Why is it that when I try to use the same way as a parameter to Set-Location it is an error? I think this may be something fundamental about the objects in Powershell. What do I need to know?
Set-Location : A positional parameter cannot be found that accepts argument 'C:\src\powershell\curdir2.ps1'.
At C:\src\powershell\curdir2.ps1:6 char:1
+ Set-Location -Path [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.De ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Location], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
Use parentheses.
As you can see in PS ISE that entire parameter is interpreted as a literal string otherwise.
And always use -LiteralPath instead of -Path to correctly handle directories with [] brackets.
Set-Location -LiteralPath ([IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition))
PS3.0+: cd -LiteralPath $PSScriptRoot
I am trying to run the below against multilpe servers using Powershell 3.0 but for some reason I am getting back that the path does not exist...even though it does?
Any ideas?
CODE:
clear
$computer = Get-Content -path c:\temp\servers.txt
foreach ($computer1 in $computer){
Write-Host $computer1
Get-Content -Path '\\$computer1\C$\Program Files\BMC Software\BladeLogic\RSCD\rscd.log' -Tail 10
}
ERROR:
SV191267 Get-Content : Cannot find path '\$computer1\C$\Program
Files\BMC Software\BladeLogic\RSCD\rscd.log' because it does not
exist. At
C:\Users\gaachm5\AppData\Local\Temp\e4651274-dcab-4a87-95a6-0f11437a7187.ps1:7
char:1
+ Get-Content -Path '\$computer1\C$\Program Files\BMC Software\BladeLogic\RSCD\rs ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (\$computer1\C$...c\RSCD\rscd.log:String) [Get-Content],
ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
SV193936 Get-Content : Cannot find path '\$computer1\C$\Program
Files\BMC Software\BladeLogic\RSCD\rscd.log' because it does not
exist. At
C:\Users\gaachm5\AppData\Local\Temp\e4651274-dcab-4a87-95a6-0f11437a7187.ps1:7
char:1
+ Get-Content -Path '\$computer1\C$\Program Files\BMC Software\BladeLogic\RSCD\rs ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (\$computer1\C$...c\RSCD\rscd.log:String) [Get-Content],
ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
try:
"\\$computer1\C`$\Program Files\BMC Software\BladeLogic\RSCD\rscd.log" -Tail 10
In single quotes ' the variable are not expanded but treated as literal as $computer1, the $ for the $admin share must be escaped with a backtick `
The path that can't be found only has one \ on the front of it, a UNC share must begin with two \'s. I can see from your code it looks like you are prefixing the two \'s but it doesn't look like it's being carried over.
I would use double quotes instead of single quotes as already pointed out, if you do that then you should not need to escape the $ character either.
Assuming a file called file.txt exists in the C:\temp folder on the local machine.
This fails:
$computer1 = "localhost"
Test-Path '\\$computer1\c$\temp\file.txt'
This works:
$computer1 = "localhost"
Test-Path "\\$computer1\c$\Temp\file.txt"