What does it mean "Could not find a part of the path"? - powershell

Is there a limit to the size of the path the get-childitem and select-string can handle? If yes what is the alternative?
When I run the following command on the path:
PS E:\KINGSTON backup5\03 Learning\Softwares\Mathematica\Mathematica 12\Mathematica Directories Backup2\C,Users,atfai,AppData,Roaming,Mathematica\Paclets\Repository\SystemDocsUpdate1-12.0.0\Documentation\English\Workflows> get-childitem -recurse -filter "*.nb" -file | select-string -pattern ".*ProcessObject.*" -casesensitive
I get the following error
select-string : The file E:\KINGSTON backup5\03
Learning\Softwares\Mathematica\Mathematica 12\Mathematica Directories
Backup2\C,Users,atfai,AppData,Roaming,Mathematica\Paclets\Repository\SystemDocsUpdate1-12.0.0\Documentation\English\Workflows\ChangeTheStyleOfPointsInA2DScatterPlot.nb
cannot be read: Could not find a part of the path 'E:\KINGSTON
backup5\03 Learning\Softwares\Mathematica\Mathematica 12\Mathematica
Directories
Backup2\C,Users,atfai,AppData,Roaming,Mathematica\Paclets\Repository\SystemDocsUpdate1-12.0.0\Documentation\English\Workflows\ChangeTheStyleOfPointsInA2DScatterPlot.nb'.
At line:1 char:47
+ ... nb" -file | select-string -pattern ".ProcessObject." -casesensitive ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Select-String], ArgumentException
+ FullyQualifiedErrorId : ProcessingFile,Microsoft.PowerShell.Commands.SelectStringCommand
Moreover if I run the same command on the following path:
PS E:\Computer Backup\Downloads - Current\Windows 10 Optimization\SoftwareDistribution.old3\Download\736aed4d238d4999f5ea5b04589077ed\Package_for_RollupFix~~amd64~~17134.677.1.6\x86_wcf-system.servicemodel_b03f5f7f11d50a3a_10.0.17134.254_none_d5ff175e12d127c0> get-childitem -recurse -filter "*.nb" -file | select-string -pattern ".*ProcessObject.*" -casesensitive
I get the error this time from get-childitem
get-childitem : Could not find a part of the path 'E:\Computer
Backup\Downloads - Current\Windows 10
Optimization\SoftwareDistribution.old3\Download\736aed4d238d4999f5ea5b
04589077ed\Package_for_RollupFix~~amd64~~17134.677.1.6\x86_wcf-system.servicemodel_b03f5f7f11d50a3a_10.0.17134.254_none_d5ff175e12d127c0'.
At line:1 char:1
+ get-childitem -recurse -filter "*.nb" -file | select-string -pattern ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ReadError: (E:\Computer Bac...5ff175e12d127c0:String) [Get-ChildItem],
DirectoryNotFoundException
+ FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand
What does it mean "Could not find a part of the path"? The drive E has NTFS file system which is supported by Windows so its powershell commands should be able to handle it? What is going on here?
BTW I can access both paths from the Windows explorer and open the files in the notepad. So the paths exist and files are clearly not corrupt or inaccessible.

The problem is, that long paths aren't enabled on your OS, so there is a limit of 260 characters.
Depending on the version of windows you are running, this can be fixed by enabling the group policy Local Computer Policy > Computer Configuration > Administrative Templates > System > Filesystem > NTFS > Enable NTFS long paths.
If you don't have that option, changing the value of the registry key LongPathsEnabled at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem from 0 to 1 does the job as well.

If you can't use the registry or group policy fix of the other answer you may be able to work around this by using the prefix \\?\E:\folder1\...
To specify an extended-length path, use the "\?" prefix. For example, "\?\D:\very long path".
[...]
The "\?" prefix can also be used with paths constructed according to
the universal naming convention (UNC). To specify such a path using
UNC, use the "\?\UNC" prefix. For example, "\?\UNC\server\share",
where "server" is the name of the computer and "share" is the name of
the shared folder.
Ref: https://learn.microsoft.com/en-ca/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd

Related

I want to take the output of Get-PSDrive to get the drive letter of all drives and do a search for ISO's and use the path from the Get-PSDrive

I am trying to use Get-PSDrive to put all the drive letters used by disks into a string that returns each letter (That works)
I am having problems using the $ISODeviceLetter variable to use it as a path to search all drives for .ISO files.
$ISODeviceLetter = Get-PSDrive | Select-Object -ExpandProperty 'Name' | Select-String -Pattern '^[a-z]:$'
$ISOLocation = Get-ChildItem -Path $ISODeviceLetter -Recurse -Include *.ISO
This is the error I get:
Get-ChildItem : Cannot find path 'C:\Users\Administrator\C' because it does not exist.
At line:1 char:16
+ ... OLocation = Get-ChildItem -Path $ISODeviceLetter -Recurse -Include *. ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\Administrator\C:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
I see by the error the get-childitem is using the default location which is the C:\Users\Administrator.
The desired output is to pass $ISODriveLetter as the Path for all drives on the server "C:","D:","E:", so all the drives can be searched for .ISO files.
Thanks ahead of time for the help.
The issue is that when referencing drives, they have to be distinguished using a colon (:) to disambiguate the drive from a regular folder/file:
Use the Foreach-Object command to append the Colon to each drive letter returned.
Changed the filter from -Include to -Filter, to speed up the process as -Filter is implemented by the FileSystemProvider, and you're also not looking for multiple files.
Added -File switch for a more efficient query as well, since an .ISO extension is associated to a file.
$ISODeviceLetter = [array](Get-PSDrive |
Where-Object -FilterScript {$_.Name -match "^.$"}).Foreach{
$_.Name + ':'
}
$ISOLocation = Get-ChildItem -Path $ISODeviceLetter -File -Recurse -Filter *.ISO
Bonus:
You can use Simplified Syntax to achieve the same results as above for better readability:
$ISODeviceLetter = (Get-PSDrive).Where{$_.Name -match "^.$"} |
Select -exp Name | Foreach Insert -ArgumentList 1,':'
Only real "downside" of this is, that you're using the pipeline even more. Even though it may not affect the speed in your return for this example, other time sensitive tasks can take quite a performance hit using the pipeline.

Why does PowerShell's Get-Content return "cannot be read/access denied" when cmd's type works for same file?

I employ a user-defined function, called searchfor, from a PowerShell console prompt (Run as Administrator) to find files containing strings:
PS repo> gc Function:\searchfor
param([string]$root, [string[]]$includeexpression, [string]$regexp)
$fullpath = convert-path $root
Get-ChildItem -force -recurse $fullpath -include $includeexpression | Select-String $regexp
This has recently started to fail on some files with the following "cannot be read/access denied" error message:
Select-String : The file C:\builds\repo\LightweightSerialization\LightweightSerializationWriter.cs cannot be read: Access to the path 'C:\builds\repo\LightweightSerialization\LightweightSerializationWriter.cs' is denied.
At C:\Users\schlagermeier\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1:174 char:71
+ ... recurse $fullpath -include $includeexpression | Select-String $regexp
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Select-String], ArgumentException
+ FullyQualifiedErrorId : ProcessingFile,Microsoft.PowerShell.Commands.SelectStringCommand
An attempt to read the file interactively with Get-Content fails with the same error. However, if I launch a Command Prompt (cmd.exe), also using Run as Administrator, I can read the file content with the type command.
I've looked at the file's permissions and acl, and it doesn't appear any different to others in the same folder which can be read by PowerShell. Can anybody suggest any possible causes and how these might be identified and fixed?

Misbehaving Get-ChildItem Operation in PowerShell

There is a back-end SQL DB contains "managed folders" in the form of UNC paths. Using SQL queries in PowerShell I have a loop that will work it's way through these folders and run a GCI operation against them to work out how much disk space they are using.
$managedFolder = "\\server\share\folder\subfolder"
For the sake of the question, $managedFolder is declared as above. The failing command below:
$diskTrendsInitialUsage = "{0:N2}" -f ((Get-ChildItem $managedFolder -Recurse -Force | Measure-Object -Property Length -Sum).Sum / 1GB)
Now if I were to run this command manually in PS console it's fine, it pulls back data. But as soon as it's packaged in a script, it fails with the below error. The folder is accessible from the server, as it works fine from a local PS console session.
ERROR: Get-ChildItem : Invalid Path: '\\server\share\folder\subfolder'.
AddManagedFolder.psf (17): ERROR: At Line: 17 char: 42
ERROR: + $diskTrendsInitialUsage = "{0:N2}" -f ((Get-ChildItem $managedFolder -Recurse ...
ERROR: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ERROR: + CategoryInfo : NotSpecified: (:) [Get-ChildItem], ArgumentException
ERROR: + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.GetChildItemCommand
ERROR:
I'm stumped.
The problem with your path is that it does not have any indication about which provider to use, so PowerShell just use current one. And if current provider is not a file system provider, then it will fail. So you need to specify provider in path, to allow PowerShell to choose right one regardless of current provider:
$managedFolder = "filesystem::\\server\share\folder\subfolder"
My guess is your are using the SQL PS cmdlets prior to running GCI, this is changing your provider path to SQL: which is what is causing GCI to be unhappy.
Prior to running GCI do cd c:\ to change the path back to the file system and GCI will work.

Powershell script to omit traversing access denied folders from a list of folders

I was trying to do a script to list extract the folders and subfolders and the number of files for a particular path of directory. How to exclude the folders whose access is denied in the script?
I used the get-childitem code snippet along with where {$_.permission -match "read", I don't know if what I am trying is correct or not. I ended up with the following error:message:
CategoryInfo : ReadError: (\support....-242\New folder:String) [Get-ChildItem], IOException
+ FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand
You can set your error action preference per cmdlet like:
Get-ChildItem -recurse -ErrorAction SilentlyContinue | ? {$_.permission -match "read"}
Or you can set it per script using the System variable:
$ErrorActionPreference = "SilentlyContinue"
Get-Help about_CommonParameters

Parsing Shortcuts in Powershell

I have some code which is trying to make a copy of a directory which contains shortcuts:
# Create a directory to store the files in
mkdir "D:\backup-temp\website.com files\"
# Search for shortcuts so that we can exclude them from the copy
$DirLinks = Get-ChildItem "\\web1\c$\Web Sites\website\" -Recurse | ? { $_.Attributes -like "*ReparsePoint*" } | % { $_.FullName }
# Execute the copy
cp -recurse -Exclude $DirLinks "\\web1\c$\Web Sites\website\*" "D:\backup-temp\website.com files\"
But when I execute the script I get the following error:
Copy-Item : The symbolic link cannot be followed because its type is disabled.
At C:\scripts\backup.ps1:16 char:3
+ cp <<<< -recurse "\\web1\c$\Web Sites\website\*" "D:\backup-temp\website.com files\"
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId :
System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand
It seems the script is getting hung up on a symbolic link (I'm assuming the shortcut) that I'm trying to exclude in the fourth line of the script.
How can I tell powershell to ignore/exclude shortcuts?
Thanks,
Brad
If you are on V3 or higher you can eliminate the reparse points like so:
Get-ChildItem "\\web1\c$\Web Sites\website" -Recurse -Attributes !ReparsePoint |
Copy-Item -Dest "D:\backup-temp\website.com files"
On V1/V2 you can do this:
Get-ChildItem "\\web1\c$\Web Sites\website" |
Where {!($_.Attributes -bor [IO.FileAttributes]::ReparsePoint)} |
Copy-Item -Dest "D:\backup-temp\website.com files" -Recurse
So it turns out that the issue I faces is explained in this Microsoft Blog Post:
http://blogs.msdn.com/b/junfeng/archive/2012/05/07/the-symbolic-link-cannot-be-followed-because-its-type-is-disabled.aspx
Essentially on the server I am running the powershell script from I needed to run the following command:
fsutil behavior set SymlinkEvaluation R2R:1
This allows Remote to remote symbolic links. Once this is in place the above powershell commands run as expected without errors.