This script exports the basic file metadata in PowerShell to a .csv.
PS K:\> Get-childitem -recurse -file | select-object length,lastwritetime,fullname | export-csv filelist.csv -notypeinformation
It works great on simple directory structures of 10-20K files, but when I run it on 500K+ files of complex, multi-level directory structures it freezes or gives me error:
At line:1 char:1
+ Get-childitem -recurse -file | select-object length,lastwritetime,ful ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
+ FullyQualifiedErrorId : CallDepthOverflow
Is this a problem with the -recurse or else? Using PowerShell 5 1 (Major Minor).
Test to see how long the filepaths are.
If the filepaths are more than 248 characters... That may be why you are getting the error.
To check to see if any come back with more than 248 characters you can do
Get-childitem "filepath" -recurse | % {
$filepath = $_.FullName
$charactercount = ($filepath | Measure-Object -Character).Characters
If ($charactercount -gt 248){write-host $filepath}
}
Related
I have the following code:
$MoveSheet0101AfterRender = get-ChildItem $Sheet01 -recurse | where {$_.name -match "Model 01-02 - $TodayDate"} | Move-Item -Destination (new-item -type directory -force ($OldSheets + $newSub)) -force -ea 0
Basically it asks PowerShell to look for files with Model 01-02 - $TodayDate in the name and move these files to the directory defined in $OldSheets, but for some reason it is copying files that have a slight variation in the name.
For example: if the file is named Model 01-03 - $TodayDate, for some reason the script is moving too.
I tried changing -match to -contains, but that way no files were moved.
Remembering that Model 01-02 - $TodayDate is just a part of the file name, for this reason I cannot use -eq.
How can I resolve this?
Update:
I have another variable called $MoveSheet0103AfterRender and its code is this:
$MoveSheet0103AfterRender = get-ChildItem $Sheet01 -recurse | where {$_.name -eq "$ClientName - Modelo 01-03 - $TodayDate.txt"} | Move-Item -Destination (new-item -type directory -force ($OldSheets + $newSub)) -force -ea 0
What seems to be happening is that this variable is being executed even though it's not in the code, because when I delete it the code works as expected.
What is the reason for this?
I'm confused by how much slower one of these commands is compared to the other.
This command finds the size of the C:\ drive, by recursively finding the size of every subfolder in C:\
$len = 0
gci -path C:\ -recurse -force -ErrorAction SilentlyContinue | % { $len += $_.length}
This command finds the name of every folder on the C:\ drive, by recursively looking through every folder on the C:\ drive
$result = gci -path C:\ –recurse -force -directory -ErrorAction SilentlyContinue | %{$_.fullName}
Why is the first one so much faster than the second? Is there some kind of caching going on for folder sizes? Is it just a matter of string manipulation being orders of magnitude slower than integer manipulation?
Note: as written your first command pushes out a bunch of error messages I cancelled the command because it ran on for some minutes! Although directories have a length property it is the length of the Full Diretory Path and not the size of the directory in bytes.
The property 'length' cannot be found on this object. Verify that the property
exists.
At line:2 char:68
+ ... ecurse -force -ErrorAction SilentlyContinue | % { $len += $_.length}
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], PropertyNotFoundException
+ FullyQualifiedErrorId : PropertyNotFoundStrict
So I added the -File switch parameter.
PS> $len = 0
Measure-Command -Expression {
gci -path C:\ -File -recurse -force -ErrorAction SilentlyContinue | % { $len += $_.length}}
TotalSeconds : 58.5945269
PS> $len = 0
Measure-Command -Expression {
$x = gci -path C:\ -File -recurse -force -ErrorAction SilentlyContinue
ForEach ($File in $x) { $Len += $file.length}
}
TotalSeconds : 48.99365
As you can see using the Pipe is considerably slower that saving to a variable, an array in this case, and then processing from that.
I edited out the redundant info output by Measure-Command
In the second command you are not processing files only directories (-Directory) and you are not calculating size thus making it faster.
As you can see this command only returns an array of Strings of the directory paths. (again edited for brevity).
PS> $result.count
118148
PS> $result[0] | gm
TypeName: System.Stri
Name MemberType Definition
---- ---------- ----------
Chars ParameterizedProperty char Chars(int index) {get;}
Length Property int Length {get;}
PS> $result[0].Length
14
PS> $result[0]
C:\$GetCurrent
HTH
On powershell 5.1
Using this within a foreach loop, ex:
foreach ($i in $folder.subfolders) {
if( $i.path -like "*node_modules" ){
Remove-Item $i.path -Force -Recurse
}
}
I keep running into this particular error:
+ CategoryInfo : WriteError: (_node_modules_r...dationpath.html:FileInfo) [Remove-Item], DirectoryNotFoundException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item C:\topDir\js\node_modules\ram
l-1-parser\documentation\interfaces\_node_modules_raml_definition_system_node_modules_raml_typesystem_dist_src_index_d_.numbertype.html:
Could not find a part of the path '_node_modules_raml_definition_system_node_modules_raml_typesystem_dist_src_index_d_.numbertype.html'.
At C:\topDir\re.ps1:12 char:11
+ Remove-Item $i.path -Force -Recurse
The files causing the error all exist and I've checked the path and as far as my eyes can tell, they're correct?
Only thing I can make out is that the filenames are abnormally long. But surely that can't be the cause of this?
Long UNC names are problematic to delete. This is a OS specific thing, that limit is 260 characters.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
On Windows 10 you can enable long path names, but that does not work in all situations. I some cases you have to result to using the short name, and this requires some conversion effort.
And ditto with what 'Beacon Bits' states, because there is no .subfolder property or method. You can see this by doing...
(gci D:\Temp) | Get-Member | Select Name,MemberType
If you are after the file in a parent or subfolder, you use the...
FullName Property
Something like...
(gci 'D:\Temp\*.txt' -Recurse).FullName
Results
D:\Temp\diff\TestFile_2.txt
...
D:\Temp\Duplicates\BeforeRename1\FsConfig.txt
...
D:\Temp\Duplicates\dup5\SomeRandomThing.txt
...
I have windows 7
I have a folder name employeephotos about 100 pictures that all have name_last.
I would like to remove all the "_" from the files in the folder and make the files namelast.jpg.
I have try this command
PS U:\desktop\employeephotos> Dir | Rename-Item -NewName { $_.name replace"_",""}
Rename-Item : Source and destination path must be different.
At line:1 char:18
+ Dir | Rename-Item <<<< -NewName { $_.name -replace"_",""}
+ CategoryInfo : WriteError: (U:\desktop\employeephotos\New folder:String) [Rename-
+ FullyQualifiedErrorId : RenameItemIOError,Microsoft.PowerShell.Commands.RenameItemCommand
(From my comments)
Rename-Item is a PowerShell command, so you need to be working in PowerShell instead of the cmd.exe command prompt.
It might be picking up files with no _ in the name, the rename does not change the name, and they cannot be given the same name, so it fails. Try dir *_* at the start to only find and rename files with _ in the name.
You might try something like this:
Get-ChildItem -Filter "*_*" | Foreach-Object { Rename-Item -Path $_.Name -NewName $_.Name.Replace("_", "") -WhatIf }
If it produces the output you're looking for, then just pull the -WhatIf parameter off.
I am trying to move a list of files from one directory to another. The catch is, When the items are moved to the new directory, I want to automatically organize them.
Ex..
I have a folder of thousands of filenames.
All filenames are relative to a user's userID. Some users have multiple files in this folder, so it appends a number onto the end of the name. I.E. susy.txt, susy1.txt, susy2.txt, carl.txt, carl1.txt, etc...
What I am trying to do is create a specific folder (in the new directory) for each user that has multiple files, and move all associated files into that folder. So I notice there are multiple susy documents. So I want to create a folder named Susy and place susy.txt, susy1.txt, and susy2.txt into it... And so on for all files.
Is it even possible to do this as a batch file, if so can someone point me in the correct direction on doing this? I have a small amount of knowledge in writing batch scripts, and would like to take this as an opportunity to learn more.
This is very similar to a question I have asked earlier. File and Folder Manipulation in Powershell. I am very thankful for the responses I received, they helped me greatly. The answer from Adi Inbar was exactly what I needed, at the time. However, I was forced to make a modification, which I have tried myself.
Adi Inbar's Answer
Get-ChildItem | ?{$_.Name -match '(\D+)\d*\.txt'} | %{
md $matches[1] -ea SilentlyContinue
Move-Item $_ $matches[1]
}
Short sweet and too the point, exactly what I needed. However it only works for for files that are going to be organized but stay in the same parent folder.
This is what I have attempted:
Get-ChildItem –path "P:\My Documents\Org Test\Test1" | Where{$_.Name -match '(\D+)\d*\.txt'} | Foreach{
md P:\'My Documents'\'Org Test'\Test2\$matches[1] -ea SilentlyContinue
Move-Item $_ P:\'My Documents'\'Org Test'\Test2\$matches[1]
}
To my knowledge and basic understanding this should work... But I am getting an error saying Move-Item : Cannot create a file when that file already exists.
At P:\My Documents\Org Test\Test.ps1:3 char:3
+ Move-Item -Path P:\'My Documents'\'Org Test'\Test1\$_ -destination P:\'M ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (P:\My Documents...t1\Johnny123.txt:FileInfo) [Move-Item], I
+ FullyQualifiedErrorId : MoveFileInfoItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand
I am sure that it is on the tip of my tongue, but I cannot get it. I have very basic powershell scripting experience and just need a quick fix.
EDIT:
I have been able to "resolve" my issue by using this script:
Get-ChildItem –path P:\'My Documents'\'PST Org Script'\Test1 | Foreach-Object{
move-item -Path $_.fullname -Destination "P:\My Documents\PST Org Script\Test2" -ea SilentlyContinue }
cd P:\'My Documents'\'PST Org Script'\Test2
Get-ChildItem | ?{$_.Name -match '(\D+)\d*\.txt'} | %{
md $matches[1] -ea SilentlyContinue
Move-Item $_ $matches[1]
}
I am curious. I feel like this can be done in the 3 lines of code I have above. This seems like a little redundant. But what do I know.
Thanks
Try this:
$srcPath = 'P:\My Documents\PST Org Script\Test1'
$dstPath = 'P:\My Documents\PST Org Script\Test2'
Get-ChildItem $srcPath | Where {$_.Name -match '(\D+)\d*\.txt'} |
Foreach {$targetDir = Join-Path $dstPath $matches[1]
md $targetDir -ea 0
Move-Item $_ $targetDir -WhatIf}
I have been able to resolve my issue using this:
Get-ChildItem –path P:\'My Documents'\'PST Org Script'\Test1 | Foreach-Object{
move-item -Path $_.fullname -Destination "P:\My Documents\PST Org Script\Test2" -ea SilentlyContinue }
cd P:\'My Documents'\'PST Org Script'\Test2
Get-ChildItem | ?{$_.Name -match '(\D+)\d*\.txt'} | %{
md $matches[1] -ea SilentlyContinue
Move-Item $_ $matches[1]
}
However I feel, there is a shorter, simpler way of doing this via some variation of the method I entered earlier in my original question.