So, the folder structure looks like this:
RootFolder
RootFolder
SubFolder1
SubSubFolder1
totals.txt
SubSubFolder2
totals.txt
SubFolder2
SubSubFolder1
totals.txt
SubSubFolder2
totals.txt
What I want to do is recursively walk through these Subfolders for the totals.txt file. Read content, and copy lines 22,26,30,34,38,and 42 (with first line being 0 not 1)into a single combined file.
I started with this code:
Get-ChildItem -Recurse | Where-Object {$_ -like "totals.txt" } | Get-Content | Select-Object -Index 22,26,30,34,38,42 | Add-Content "DataInportFile.txt"
However this only finds RootFolder\SubFolder\SubSubFolder\totals.txt and then exits script. Not what I'm looking for...
What I need is the above script to continue searching recursively for the next file and next until all directories have been searched in structure. So I used this:
Get-ChildItem -Recurse | ForEach-Object {$_ -like "totals.txt" } | Get-Content | Select-Object -Index 22,26,30,34,38,42 | Add-Content "DataInportFile.txt"
However, this script errors
C:\Users\user1\scripts\Untitled1.ps1:1 char:69
+ ... urse | ForEach-Object {$_ -like "totals.txt" } | $_.filename #| Get- ...
+ ~~~~~~~~~~~
Expressions are only allowed as the first element of a pipeline.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ExpressionsMustBeFirstInPipeline
I could use some help figuring out the rest of this powershell script. So close but no joy. Thanks for the help.
Realized I needed to walk through the array
For other's reference, this code works as required:
Get-ChildItem -Recurse | Where-Object {$_ -like "totals.txt" } |
%{
(Get-Content $_.FullName) | Select-Object -Index 22,26,30,34,38,42 | Add-Content "DataInportFile.txt"
}
Related
So, i need to save a string that was replaced on files.
I'm doing something wrong, but i`m not be able to figure it out, what!
My code:
Get-ChildItem -Path C:\Users\user\Documents -Recurse -Include "*.txt" -File | Select-String -Pattern \b192\.168\.10\.2\b , \b192\.168\.10\.11\b -AllMatches -List | Foreach-Object { $_ -replace '\b192\.168\.10\.2\b', "DEV" -and $_ -replace '\b192\.168\.10\.11\b', "QUAL" | Set-Content $_}
And gives-me the following error:
Set-Content : Could not open the alternate data stream '1:192.168.10.11' of the file 'C:\Users\user\Documents\result.txt'.
At line:1 char:323
+ ... place '\b192\.168\.10\.11\b', "QUAL" | Set-Content $_}
+
+ CategoryInfo : ObjectNotFound: (C:\Users\paulo....ents\result.txt:String) [Set-Content], FileNotFoundException
+ FullyQualifiedErrorId : GetContentWriterFileNotFoundError,Microsoft.PowerShell.Commands.SetContentCommand
Set-Content : Could not open the alternate data stream '1:192.168.10.11' of the file
'C:\Users\user\Documents\test.txt'
At line:1 char:323 ... place '\b192\.168\.10\.11\b', "QUAL" | Set-Content $_}
CategoryInfo : ObjectNotFound: (C:\Users\user\test.txt:String) [Set-Content], FileNotFoundException
FullyQualifiedErrorId : GetContentWriterFileNotFoundError,Microsoft.PowerShell.Commands.SetContentCommand
Thanks for any Help!
Inside the ForEach-Object block, $_ will refer to the current match result as returned by Select-String - to get the file path, reference the Path property:
... | ForEach-Object { ... |Set-Content -LiteralPath $_.Path}
The -and operator is used inside if tests like if(this -and that).
You should change the double replace actions from
$_ -replace '\b192\.168\.10\.2\b', "DEV" -and $_ -replace '\b192\.168\.10\.11\b', "QUAL"
into
$_ -replace '\b192\.168\.10\.2\b', "DEV" -replace '\b192\.168\.10\.11\b', "QUAL"
Also, if I understand the question properly, you want to find all string replacements in the file, and to get all, you need to remove the -List switch from Select-String.
Next, as Mathias explains in his answer, you need to use the Path property from the current match to get the file FullName.
However, if you pipe this through to Set-Content straight away, you will get an exception because the file then is in use and you cannot write to the same file.
Below creates a new file in the same path, with _replacements appended to the filename
# use '-Include' instead of '-Filter' if you need more file extensions to filter on
Get-ChildItem -Path 'C:\Users\user\Documents' -Recurse -Filter "*.txt" -File |
Select-String -Pattern '\b192\.168\.10\.2\b', '\b192\.168\.10\.11\b' -AllMatches |
Foreach-Object {
$file = '{0}_replacements{1}' -f [System.IO.Path]::GetFileNameWithoutExtension($_.Path),
[System.IO.Path]::GetExtension($_.Path)
$target = Join-Path -Path ([System.IO.Path]::GetDirectoryName($_.Path)) -ChildPath $file
$_ -replace '\b192\.168\.10\.2\b', "DEV" -replace '\b192\.168\.10\.11\b', "QUAL" |
Add-Content -Path $target
}
This results in a file called 'C:\Users\user\Documents\test_replacements.txt'
C:\Users\user\Documents\test.txt:4:DEV
C:\Users\user\Documents\test.txt:7:QUAL
The original file 'C:\Users\user\Documents\test.txt' will not be altered.
I want to shorten Directory with relative path:
$Dir = get-childitem C:\temp -recurse
$List = $Dir | where {$_.extension -eq ".txt"}
$List | format-table name, Directory -replace "C:\temp", ""
I get this error:
Format-Table : A parameter cannot be found that matches parameter name 'replace'.
At line:3 char:38
+ $List | format-table name, Directory -replace "C:\temp", ""
+ ~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Format-Table], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.FormatTableCommand
What's the right syntax ?
You can use a calculated property. Example:
$List | Format-Table name,
#{Name = "Directory"; $Expression = {$_.FullName -replace "C:\\temp", ""}}
A calculated property is simply a hashtable that dictates the content of the property. Calculated properties are available with formatting cmdlets that select properties and output a new custom object (e.g, Select-Object, Format-List, etc.).
(As an aside: The -replace operator uses a regular expression, so you would need to write C:\\temp instead of just C:\temp.)
If your goal is to output file system item directory names: Directory is not a property of all file system objects. Is this what you mean?
Get-ChildItem C:\Temp\*.txt -Recurse | Format-Table Name,
#{Name = "Directory"; Expression = {$_.FullName -replace 'C:\\temp', ''}}
Note how this command takes advantage of the pipeline (no need for the intermediate $List or $Dir variables).
To add to #Bill_Stewart's Answer.
$Dir = get-childitem C:\temp -recurse
$List = $Dir | where {$_.extension -eq ".txt"}
$List | format-table name, #{Label="Directory"; Expression={$_.Directory -replace "C:\\temp", ""}}
The script I am including below needs to accomplish the following tasks. It needs to get a list of servers from AD, then iterate through each of those server names and grab the second to the newest folder in a directory, rename it, and copy it to another server.
The Copy-Item command is not working when I have it in the foreach loop, as written below:
#gathering server names
$serverList = (Get-ADComputer -Filter "Name -like 'Q0*00*'" -SearchBase "OU=MPOS,OU=Prod,OU=POS,DC=N,DC=NET").name | Sort-Object | Out-File C:\Temp\MPOS\MPOSServers.txt
$serverListPath = "C:\Temp\MPOS\MPOSServers.txt"
#Retrieve a list of MPOS Print servers from text file and set to $serverNames
$serverNames = Get-Content -Path $serverListPath
#Iterate through each of the server names
foreach ($serverName in $serverNames) {
$reportServer = "a03"
Get-ChildItem "\\$($serverName)\d$\MPosLogs\Device" |
Where { $_.PSIsContainer } |
Sort CreationTime -Descending |
Select -Skip 1 |
Select -First 1 |
ForEach-Object {
Rename-Item -Path $_.FullName -NewName ("$serverName" + "_" + $_.Name) -PassThru |
Copy-Item -Destination "\\$($serverName)\c$\temp\MPOS\Logs"
}
}
However, it works fine if I am testing it outside of the ForEach loop, as written below:
Get-ChildItem "\\$($serverName)\d$\MPosLogs\Device" |
Where { $_.PSIsContainer } |
Sort CreationTime -Descending |
Select -Skip 1 |
Select -First 1 |
ForEach-Object {
Rename-Item -Path $_.FullName -NewName ("$serverName" + "_" + $_.Name) -PassThru |
Copy-Item -Destination "\\$($serverName)\c$\temp\MPOS\Logs"
}
Any ideas as to why it is not working in the full script? I am not changing anything when I test it, I am just running the above commands without being in the ForEach loop. It is completing the rest of the tasks, except for the folder copies. The folder copy only works if I am testing it outside of the ForEach loop on a single server.
When I say "it doesn't work", there are no errors or anything like that. It simply is not copying the folders.
Thank you! :)
LG
#MikeGaruccio well that is extremely embarrassing. I think I have just been staring at this script for too long, and did not realize that I was not actually copying the folders to $reportServer - it's a good thing you asked!!! It definitely matters. All is well now, after changing the final $serverName to actually read $reportServer. Thank you, and sorry for wasting your time...I appreciate your help a lot.
I'm trying to execute following commands to clear files in a temporary directory. If there are multiple files for a particular day I should keep only the latest file.
$groups = get-ChildItem -Path "D:\Temp\Archive" -Filter "*_bak.zip" | ?{-not $_.PsIsContainer} | Group {$_.LastWriteTime.ToString("yyyy-MM-dd")}
if($groups -ne $NULL){
ForEach ($files in $groups) {
"Count: $($files.Count)"
if ($files.Count -gt 1) {
$files | Sort LastWriteTime | Select-Object -First ($files.Count - 1) | Remove-Item -Force -WhatIf
}
}
}
But, I'm getting the following error. I'm executing these commands as an administrator. And, Execution Policy is set to Unrestricted.
Remove-Item : Cannot find path 'C:\Windows\system32\Microsoft.PowerShell.Commands.GroupInfo' because it does not exist.
At D:\User1\Tasks\Delete_backup_files.ps1:86 char:87
+ $files | Sort LastWriteTime | Select-Object -First ($files.Count - 1) | Remove-Item <<<< -Force -WhatIf
+ CategoryInfo : ObjectNotFound: (C:\Windows\syst...mands.GroupInfo:String) [Remove-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
The Remove-Item command works fine if I just use it with a UNC path.
$files.FullName doesn't have a value. I suspect this could be the issue. But, I'm not sure how to fix it. I need the grouping logic to stay as is.
I hope someone could help me out here.
Thanks!
You were actually very close. You have to pass the files within the group to the sort command, not the group itself:
$files.Group | Sort LastWriteTime | Select-Object -First ($files.Count - 1) | Remove-Item -Force -WhatIf
The error you get:
Remove-Item : Cannot find path 'C:\WINDOWS\system32\Microsoft.PowerShell.Commands.GroupInfo' because it does not exist.
Happens because Remove-Item requires a string as input. But you are passing a GroupInfo object so PS calls the ToString() method. Remove-Item interprets the resulting string as a file name located in your current location C:\WINDOWS\system32\.
Calling this powershell command and getting an error. Driving me nuts.
Prompt> get-childitem -recurse ./ *NYCSCA* | where-object { $_.Name -like
"*NYCSCA*" } | rename-item $_ -newname $_.Name.Replace(" ","_") -whatif
Here is the response:
You cannot call a method on a null-valued expression.
At line:1 char:140
+ get-childitem -recurse ./ *NYCSCA* | where-object { $_.Name -like "*NYCSCA*" } | select FullName | rename-item $_ -n
ewname $_.Name.Replace <<<< (" ","_") -whatif
+ CategoryInfo : InvalidOperation: (Replace:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
If I remove the last part, I get a list of files. Any clues? I have not grocked powershell yet, obviously.
Note: I tried to post this to superuser, but the site is consistently failing now - won't let me add this exact question.
Here it is greatly simplified. I cannot even get this classic example to work.
gci *NYCSCA* | ren $_ ($_.Name).Replace("foo","bar")
Thank you #JNK, the % did it. The solution I needed is this, in case you're interested:
gci -recurse | where-object{ $_.Name -like "*NYCSCA*"} | %{rename-item $_.FullName $_.FullName.Replace("NYCSCA","SDUSD") }
I think you need foreach-object:
get-childitem -recurse ./ *NYCSCA* | where-object { $_.Name -like
"*NYCSCA*" } | % {rename-item $_ -newname $_.Name.Replace(" ","_") -whatif}
The piped array can't be renamed as a set.
Here's a simplified version to rename files only
Get-ChildItem -Filter *NYCSCA* -Recurse |
Where-Object {!$_.PSIsContainer} |
Rename-Item -NewName { $_.Name.Replace(' ','_') } -WhatIf
(Edit: line breaks added for clarity)