Please help! i'm confused what to do.
Script split files by content:
$InPC = "C:\Scripts\"
Get-ChildItem $InPC -Filter *.prt | ForEach-Object -Process {
$basename= $_.BaseName
$m = ( ( Get-Content $_ | Where { $_ | Select-String "--------------------- Instance Type and Transmission --------------" -Quiet } | Measure-Object | ForEach-Object { $_.Count } ) -ge 2)
$a=1
if ($m) {
Get-Content $_ | % {
If ($_ -match "--------------------- Instance Type and Transmission --------------") {
$OutputFile = "$basename-$a.prt"
$a++
}
Add-Content $OutputFile $_
}
Remove-Item $_
}
}
Everything is going OK when i'm set-location to C:\Scripts. But in base case it won't work and give next error:
Get-Content : Path not found "C:\Users\a.ulianov\PRTPRT.prt".
C:\Scripts\2.ps1:23 знак:18
+ $m = ( ( Get-Content $_ | Where { $_ | Select-String "------------------ ...
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\a.ulianov\PRTPRT.prt:String) [Get-Content], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
Get-Content : Path not found "C:\Users\a.ulianov\test.prt".
C:\Scripts\2.ps1:23 знак:18
+ $m = ( ( Get-Content $_ | Where { $_ | Select-String "------------------ ...
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\a.ulianov\test.prt:String) [Get-Content], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
it's seems to work with default PS location during excuting. What i might modify in this case?
#
thanks to #Raf #Rynant here is little crooked but working solution:
$InPC = "C:\Scripts"
Get-ChildItem -Path $InPC -Filter *.prt | ForEach-Object -Process {
$basename= $_.BaseName
$m = ( ( Get-Content $_.FullName | Where { $_ | Select-String "--------------------- Instance Type and Transmission --------------" -Quiet } | Measure-Object | ForEach-Object { $_.Count } ) -ge 2)
$a = 1
if ($m) {
Get-Content $_.FullName | % {
If ($_ -match "--------------------- Instance Type and Transmission --------------") {
$OutputFile = "$InPC\$basename _$a.prt"
$a++
}
Add-Content $OutputFile $_
}
Remove-Item $_.FullName
}
}
Looks a bit messy but I think the only change you need to do is replace:
Get-Content $_
with
Get-Content $_.FullName
Related
I am trying to replace some of the sub-strings with some values across multiple files. I have written this code to do so.
$dirPath = 'C:\repos\sync_cpc_cva\ExpressV2\Parameters\AG08\KeyVault'
$ConfigPath = 'C:\repos\sync_cpc_cva\config.json'
$lookupTable = #{}
(Get-Content -Raw -Path $configPath | ConvertFrom-Json).psobject.properties | Foreach { $lookupTable[$_.Name] = $_.Value }
Get-ChildItem -Path $dirPath -Recurse -Filter *.json |
Foreach-Object {
Get-Content $_.FullName | ForEach-Object {
$line = $_
$lookupTable.GetEnumerator() | ForEach-Object {
if($line -match $_.Key) {
$line = $line -replace $_.Key, $_.Value
}
}
$line
} | Set-Content -Path $_.FullName
}
If I print the content, it has replaced all the values correctly, however, it is unable to set the contents into the same file. And I am getting following error while running the code :
Set-Content : The process cannot access the file
'C:\repos\sync_cpc_cva\ExpressV2\Parameters\AG08\KeyVault\KeyVault.USNat.json' because it is being used by another process.
At C:\repos\sync_cpc_cva\filltest.ps1:22 char:9
+ } | Set-Content -Path $_.FullName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Set-Content], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.SetContentCommand
Any idea how can I replace the sub-strings in the same file?
You have several inner foreach-object loops, so you modify the $_ operator while being used. I dont think this can work. Revolve it like this:
$lookupTable = #{}
(Get-Content -Raw -Path $configPath | ConvertFrom-Json).psobject.properties | Foreach { $lookupTable[$_.Name] = $_.Value }
$files = Get-ChildItem -Path $dirPath -Recurse -Filter *.json
foreach ($file in $files) {
$content = Get-Content $file.FullName
for($i=0;$i -lt $content.length; $i++) {
$lookupTable.GetEnumerator() | ForEach-Object {
$content[$i] = $content[$i] -replace $_.Key, $_.Value
}
}
$content | Set-Content $file.FullName
}
This regex match
$script:lstfilepath = ((Get-Content -path $script:ordfile) | Select-String -pattern "^file\s*=\s*(\\\\.*.lst)").matches.groups[1].value
Produces this error on files that do not contain the match, leaving me to believe the return is null.
Cannot index into a null array.
At line:1 char:1
+ ((Get-Content -path .\27257055-brtcop.ORD) | Select-String -pattern " ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
Yet my script never jumps to the "else", it processes everything under the "if" even if there is no match.
$script:lstfilepath = ((Get-Content -path $script:ordfile) | Select-String -pattern "^file\s*=\s*(\\\\.*.lst)").matches.groups[1].value
if (-not ([string]::IsNullOrEmpty($script:lstfilepath)))
{
###LST PROCESS
Write-Host "LST FILE PRESENT"
$script:lstpayload = Get-Content $script:lstfilepath |ForEach-Object { ($_ -split '"')[-2] }
FOREACH ($script:lstfile in $script:lstpayload)
{
$script:lstzipshortname = (-join ((48..57) + (97..122) |get-random -count 11 |% {[char]$_}))
$script:lstzipname = $script:lstzipshortname + ".zip"
7z a -spf $script:lstzipname $script:lstfile
}
Set-Location $global:ordprocessingpath
copy-item -Recurse $script:ordprocfolder c:\temp
}
else
{
###REGULAR PROCESS
$script:filepath = ((Get-Content -path $script:ordfile) | Select-String -pattern "^file\s*=\s*(\\\\.*\\)").matches.groups[1].value
$script:zipshortname = $script:ordfile
$script:zipname = $script:zipshortname + ".zip"
7z a -spf $script:zipname $script:filepath
}
EDIT:FULL SCRIPT FOR AoT
$global:ordrepopath = "C:\test_environment\ORD_REPO"
$env:path = "c:\program files\7-zip"
$global:datestr = (Get-Date).ToString("MMddyyyyhhmmss")
$global:ordlogpath = "C:\test_environment\ORD_REPO\ORD_LOGS\"
$global:ordlogcheck = "C:\test_environment\ORD_REPO\ORD_LOGS\*.log"
$global:ordlogstagingpath = "C:\test_environment\ORD_REPO\ORD_STAGING"
$global:ordlogarchivepath = "C:\test_environment\ORD_REPO\ORD_LOG_ARCHIVE"
$global:ordprocessingpath = "C:\test_environment\ORD_REPO\ORD_PROCESSING"
$global:copypath = "C:\test_environment_2\share\STAGING\PRE_STAGING"
$global:ordlogdestpath = "C:\test_environment_2\Share\Staging\Pre_staging\processed_logs"
###DEFINE LOG FILE
$script:scriptlogfile = "C:\test_environment\ORD_REPO\SCRIPT_LOGS\ORD_PROCESS_LOG_$(get-date -format `"yyyyMMdd_hhmmss`").log"
Start-Transcript -Path $script:scriptlogfile -NoClobber
if (!(Test-Path -Path $global:ordlogcheck))
{
Write-Host "NO FILES TO PROCESS"
}
else
{
### CREATE ARCHIVE DIRECTORY
New-Item -Path "C:\test_environment\ORD_REPO\Archive\$global:datestr" -ItemType Directory
$script:archivepath = "C:\test_environment\ORD_REPO\Archive\$global:datestr"
$script:ordlogfiles = Get-ChildItem -Path $global:ordlogpath -File
ForEach ($script:ordlogfile in $script:ordlogfiles)
{
Set-Location $global:ordlogpath
$script:ordlogimport = (Import-Csv $script:ordlogfile.FullName).file |sort
$script:ordprocfoldername = ($script:ordlogimport |Select-Object -First 1)
New-Item -Path "C:\test_environment\ORD_REPO\ORD_PROCESSING\$script:ordprocfoldername" -ItemType Directory
$script:ordprocfolder = "C:\test_environment\ORD_REPO\ORD_PROCESSING\$script:ordprocfoldername"
Set-Location $global:ordrepopath
$script:ordlogimport |ForEach-Object {move-item $_ $script:ordprocfolder}
Set-Location $global:ordlogpath
copy-item $script:ordlogfile $script:archivepath
move-item $script:ordlogfile $script:ordprocfolder
Set-Location $script:ordprocfolder
$script:ordfiles = Get-ChildItem $script:ordprocfolder -Include *.ord,*.nwp | ForEach-Object { $_.Name }
FOREACH ($script:ordfile in $script:ordfiles)
{
$script:ordlogcount = ($script:ordlogimport).count
$script:ordcount = ((get-childitem $script:ordprocfolder).count -1)
if ($script:ordlogcount -ne $script:ordcount)
{
WRITE-HOST "MISSING ORD FILE"
}
else
{
$script:lstfilepath = ((Get-Content -path $script:ordfile) | Select-String -pattern "^file\s*=\s*(\\\\.*.lst)").matches.groups[1].value
if (-not ([string]::IsNullOrEmpty($script:lstfilepath)))
{
###LST PROCESS
Write-Host "LST FILE PRESENT"
$script:lstpayload = Get-Content $script:lstfilepath |ForEach-Object { ($_ -split '"')[-2] }
FOREACH ($script:lstfile in $script:lstpayload)
{
$script:lstzipshortname = (-join ((48..57) + (97..122) |get-random -count 11 |% {[char]$_}))
$script:lstzipname = $script:lstzipshortname + ".zip"
7z a -spf $script:lstzipname $script:lstfile
}
Set-Location $global:ordprocessingpath
copy-item -Recurse $script:ordprocfolder c:\temp
}
else
{
###REGULAR PROCESS
$script:filepath = ((Get-Content -path $script:ordfile) | Select-String -pattern "^file\s*=\s*(\\\\.*\\)").matches.groups[1].value
$script:zipshortname = $script:ordfile
$script:zipname = $script:zipshortname + ".zip"
7z a -spf $script:zipname $script:filepath
}
}
}
}
}
If $script:lstfilepath has a previous value, the error produced by your Select-String will not overwrite the value. Therefore, you need to purge the contents of $script:lstfilepath before this code executes or declare it again. Below is a replication of your issue.
$g = "hi"
$g = (select-string -pattern "h(h)" -InputObject "tree").matches.groups[1].value
Cannot index into a null array.
At line:1 char:1
+ $g = (select-string -pattern "h(h)" -InputObject "tree").matches.grou ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
-not ([string]::IsNullOrEmpty($g))
True
$g
hi
Here is one way to solve that issue using Clear-Variable:
$g
hi
Clear-Variable g
$g = (select-string -pattern "h(h)" -InputObject "tree").matches.groups[1].value
Cannot index into a null array.
At line:1 char:1
+ $g = (select-string -pattern "h(h)" -InputObject "tree").matches.grou ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
-not ([string]::IsNullOrEmpty($g))
False
I am trying to create a log reader. The data looks like so:
2017-11-27 13:24:41,791 [8] INFO CTSipEndpoint.CLogger.provider.gsiplib [(null)] - -00001 [Info] Info | 4744 | REGISTERdialog[1] 2-e:5;t:1-3 (dn:85188)
2017-11-27 13:24:41,791 [8] INFO CTSipEndpoint.CLogger.provider.gsiplib [(null)] - -00001 [Info] Info | 4744 | REGISTERdialog[1] event 2 REG/accepted
I am trying to do the following:
Return only lines in the last 48 hours to query further.
From above return any lines that contain the following phrases: "error"
"device","does not exist", "Could not identify speaker!","warn"
So far i have only been able to get this to work in an inefficient way, which runs against the file for each phrase and appends an array. Unfortunately this means that the date time becomes non-sequential. I need to now sort the content object at the end of the script to it be in sequence, or find a way to run this query smarter. Here is my script for reference:
$logfile = "C:\users\test\desktop\programlogs.log"
$content = ""
cat $logfile |
Select-String "ERROR" -SimpleMatch |
select -expand line |
foreach {
$_ -match '(.+)\s\[(ERROR)\]\s(.+)'| Out-Null
$error_time = [datetime]($matches[1]).split(",")[0]
if ($error_time -gt (Get-Date).AddDays(-2)) {
$content += $_ + "`n"
}
}
cat $logfile |
Select-String "device" -SimpleMatch |
select -expand line |
foreach {
$_ -match '(.+)\s\[(device)\]\s(.+)'| Out-Null
$error_time = [datetime]($matches[1]).split(",")[0]
if ($error_time -gt (Get-Date).AddDays(-2)) {
$content += $_ + "`n"
}
}
cat $logfile |
Select-String "does not exist" -SimpleMatch |
select -expand line |
foreach {
$_ -match '(.+)\s\[(does not exist)\]\s(.+)'| Out-Null
$error_time = [datetime]($matches[1]).split(",")[0]
if ($error_time -gt (Get-Date).AddDays(-2)) {
$content += $_ + "`n"
}
}
cat $logfile |
Select-String "Could not identify speaker!" -SimpleMatch |
select -expand line |
foreach {
$_ -match '(.+)\s\[(Could not identify speaker!)\]\s(.+)'| Out-Null
$error_time = [datetime]($matches[1]).split(",")[0]
if ($error_time -gt (Get-Date).AddDays(-2)) {
$content += $_ + "`n"
}
}
cat $logfile |
Select-String "Warn" -SimpleMatch |
select -expand line |
foreach {
$_ -match '(.+)\s\[(Warn)\]\s(.+)'| Out-Null
$error_time = [datetime]($matches[1]).split(",")[0]
if ($error_time -gt (Get-Date).AddDays(-2)) {
$content += $_ + "`n"
}
}
$content = $content | select -uniq
$file = "c:\temp\shortenedlog.txt"
$content| Add-Content -Path $file
Here's a short take, let me know if this helps or if needs tweaking:
$newlog=#()
$logfile = get-content C:\temp\programlogs.log
$searchFor="error","device","does not exist","Could not identify speaker!","warn"
foreach($line in $logfile){
if($line.Length -gt 18){
$datetime=date $line.substring(0,$line.indexof(","))
if(((date)-$datetime).TotalHours -lt 49){
$keep=$false
foreach($item in $searchFor){
if($line.contains($item)){ $keep=$true }
}
if ($keep){$newlog+=$line}
}
}
}
$newlog | sort | % {add-content C:\temp\NewLog.log $_}
Came up with a solution which I have fed in the days i am interested in, followed by the search criteria. Used this solution as works quickly.
#Set parameters.
$File = "c:\temp\RefinedLogs.txt"
$DateParam = (Get-Date).AddDays(-1).ToString('yyyy-MM-dd')
$DateParam1 = (Get-Date).ToString('yyyy-MM-dd')
$SearchForDate = #("$dateparam", "$dateparam1")
$SearchFor=#("error","device","does not exist","Could not identify speaker!","warn")
#Filter file with dates set in $SearchForDate.
$DateFiltered = Get-Content '.\MyAPP.log' | Select-String -Pattern $SearchForDate -SimpleMatch
#Filter variable for phrases set in $SearchFor.
$Content = $DateFiltered | Select-String -Pattern $SearchFor -SimpleMatch
#Make results readable
ForEach($line in $content){
$Object = "$line" + "`n"
$FinalResult += $Object
}
#Output results.
write-host $FinalResult
I need create this list to allow an other program to properly work. I use this code:
function analyse {
Param(
[parameter(Mandatory=$true)]
[String]$newPath
)
cd $newPath
dir | Foreach-Object {
$data = Get-Content -Path o:\******\public\ParcoursArborescence\Limitless\data.txt
if ($_.PsisContainer -eq $True) {
$testPath = $_.FullName + ";"
$name = $testPath
$testPath = $data -match [regex]::escape($testPath)
$testpath
if($testPath.Length -eq 0) {
$name | Out-File -Append "o:\******\public\ParcoursArborescence\Limitless\data.txt"
if ($_.FullName.Length -gt 248) {
"ecriture"
$result += $_.FullName + "`r"
} else {
"nouvelle analyse"
$_.Fullname
analyse $_.FullName
}
}
} else {
$testPath = $_.Directory.FullName + ";"
$name = $testPath
$testPath = $data -match [regex]::escape($testPath)
if($testPath.Length -eq 0) {
$name | Out-File -Append "o:\******\public\ParcoursArborescence\Limitless\data.txt"
$_.FullName.Length
if ($_.FullName.Length -gt 260) {
"ecriture2"
$result += $_.Directory.Name + "`r"
}
}
}
}
$result | Out-File -Append "o:\******\public\ParcoursArborescence\Limitless\bilanLimitless.txt"
}
But it takes hours and hours... I need to use this in thousands of folders. So, do you have any idea about how could it get faster ?
Maybe I'm oversimplifying things here, but why not list all the files at once, and test their FullName Length (PS 3.0 needed for the -File parameter of Get-ChildItem) ?
$maxLength = 248
Get-ChildItem $newPath -Recurse |
Where-Object { ($_.FullName.Length -gt $maxLength) } |
Select-Object -ExpandProperty DirectoryName -Unique |
Out-File "overlength_paths.txt"
For PS 2.0:
$maxLength = 248
Get-ChildItem $newPath -Recurse -File |
Where-Object { ($_.FullName.Length -gt $maxLength) -and (-not $_.PSisContainer) } |
Select-Object -ExpandProperty DirectoryName -Unique |
Out-File "overlength_paths.txt"
The snippet (Get-Content $_.FullName | Select-Object -First 1) is called three times. The aim is to declare it as a variable to avoid code duplication.
Get-ChildItem "$env:ChocolateyInstall\lib\eclipse.*" -Recurse -Filter "eclipseInstall.zip.txt" |
ForEach-Object{ if (((Get-Content $_.FullName | Select-Object -First 1) -match "eclipse") -and (Test-Path -Path (Get-Content $_.FullName | Select-Object -First 1))){Remove-Item -Recurse -Force (Get-Content $_.FullName | Select-Object -First 1)}}
Attempt
$a = (Get-Content $_.FullName | Select-Object -First 1)
Get-ChildItem "$env:ChocolateyInstall\lib\eclipse.*" -Recurse -Filter "eclipseInstall.zip.txt" |
ForEach-Object{ if (($a -match "eclipse") -and (Test-Path -Path (Get-Content $_.FullName | Select-Object -First 1))){Write-Host "hello"}}
Result
PS C:\Windows\system32> . "C:\temp\powershelltest\test.ps1"
Get-Content : Cannot bind argument to parameter 'Path' because it is null.
At C:\temp\powershelltest\test.ps1:1 char:19
+ $a = (Get-Content $_.FullName | Select-Object -First 1)
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-Content], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetContentC
ommand
You can assign a snippet of code to a variable like this:
$a = { Get-Content $_.FullName | Select-Object -First 1 }
Then execute the snippet at any time with & $a (you would need to pipe an object to it). I'm not sure this is necessary in your example though.