cmdlet Get-Content at command pipeline position 1 - powershell

I am trying to recursively find references of Constants.cs of an any other .cs files in a directory containing files with Paths. Name of the files are stored procedures and they have the references(Paths) for that stored procedure.
This is PowerShell Script that i have written.
[CmdletBinding()]
param(
[Parameter(Position=0, Mandatory=$true)]
[string]$ProceduresFile,
[Parameter(Position=1, Mandatory=$true)]
[string]$ReferencesDir,
[Parameter(Position=2, Mandatory=$true)]
[string]$Project,
[Parameter(Position=3, Mandatory=$false)]
[string]$OutputPath = "."
)
$ErrorActionPreference = "Stop"
$storedProcFromFile = [IO.File]::ReadAllLines($ProceduresFile)
function Search-PSfile
{
param(
[string] $ReferencesDir,
[string] $Project,
[string] $file
)
$procedureName = $file.Split(".")[0].ToLower()
$textName = "${procedureName}.txt"
$pattern = "\b${Project}\.\b"
#check for Constant.cs files in project directory-- returs true if present
$isConstantFile = [bool](Get-ChildItem -Path $ReferencesDir -Filter $textName -Recurse |
Get-Content |
Select-String -Pattern "\bConstants.cs\b" |
Select-String -Pattern $pattern -Quiet)
#check for .cs files in project directory besides Constants.cs .. returs true if present
$isOtherCsFile = [bool](Get-ChildItem -Path $ReferencesDir -Filter $textName -Recurse |
Get-Content |
Select-String -Pattern "\b.cs\b" |
Select-String -Pattern "\bConstants.cs\b" -NotMatch |
Select-String -Pattern $pattern -Quiet)
$filePattern = "\b${procedureName}\b"
#check for .sql files other than itself.. returs true if present
$isUsedSql = [bool](Get-ChildItem -Path $ReferencesDir -Filter $textName -Recurse |
Get-Content |
Select-String -Pattern "\.sql" |
Select-String -Pattern $filePattern -NotMatch -Quiet)
# if there are no constant files and no .sql file and no there .cs files then SP is not used
If(!$isConstantFile -and !$isUsedSql -and !$isOtherCsFile)
{
return $false
}
# If there are Constants.cs then write SP name in Used.txt end function
Elseif ($isConstantFile)
{
return $true
}
# If there are other .cs files then check if SP is commented out if yes then 'not used' else 'used'
Elseif ($isOtherCsFile)
{
Get-ChildItem -Path $ReferencesDir -Filter $textName -Recurse |
Get-Content |
Select-String -Pattern "\b.cs\b" |
Select-String -Pattern "\bConstants.cs\b" -NotMatch |
Select-String -Pattern $pattern |
ForEach-Object{
$isUnCommented = [bool](Get-Content |
Select-String -Pattern $filePattern |
Select-String -Pattern "\/\/" -NotMatch -Quiet)
if($isUnCommented)
{
return $true
}
else
{
return $false
}
}
}
# if there are no .cs files only .sql files then do a recusion and check for that .sql file
Elseif ($isUsedSql)
{
Get-ChildItem -Path $ReferencesDir -Filter $textName -Recurse |
Get-Content |
Select-String -Pattern "\.sql" |
Select-String -Pattern $filePattern -NotMatch |
ForEach-Object{
$sqlFile = (Get-Item $_).Name
Search-PSfile -ReferencesDir $ReferencesDir -Project $Project -file $sqlFile -OutputPath $OutputPath
}
}
}
function Write-PSfile
{
param(
[string]$OutputPath,
[string]$File,
[string]$FileName,
[string]$Text
)
$fileExist = Test-Path "${OutputPath}\${FileName}"
if(!$fileExist)
{
$line = "${File} | ${Text}"
New-Item -Path $OutputPath -Name $FileName -ItemType "file" -Value $line
}
else {
$line = "${File} | ${Text}"
$path = "${OutputPath}\${FileName}"
Add-Content -Path $path -Value $line
}
}
$storedProcFromFile | ForEach-Object{
$isUsed = Search-PSfile -ReferencesDir $ReferencesDir -Project $Project -file $_ -OutputPath $OutputPath
if($isUsed)
{
Write-PSfile -OutputPath $OutputPath -File $_ -FileName "Used.txt" -Text "Used"
}
else
{
Write-PSfile -OutputPath $OutputPath -File $_ -FileName "NotUsed.txt" -Text "Not Used"
}
}
Write-Host "Script Ran Successfully"
I am not sure why I am getting cmdlet Get-Content at command pipeline position 1 for second elseif Elseif ($isOtherCsFile)statement but others are working fine. Any Suggestion is welcome. Thankyou.

Related

How to get this PowerShell output as a Table view?

I need to get this PowerShell output in a Table view.Also, need to within quotation marks.
Current Output format:
Testing\Dump\DumpText-1.txt Dump\DumpText-1.txt
Testing\Dump\DumpText-2.txt Dump\DumpText-2.txt
Testing\Dump\SubDump1\DumpText-1.txt SubDump1\DumpText-1.txt
Testing\Dump\SubDump1\DumpText-2.txt SubDump1\DumpText-2.txt
Testing\Dump\SubDump2\Screenshot.png SubDump2\Screenshot.png
Required Output Format:
"Testing\Dump\DumpText-1.txt" "Dump\DumpText-1.txt"
"Testing\Dump\DumpText-2.txt" "Dump\DumpText-2.txt"
"Testing\Dump\SubDump1\DumpText-1.txt" "SubDump1\DumpText-1.txt"
"Testing\Dump\SubDump1\DumpText-2.txt" "SubDump1\DumpText-2.txt"
"Testing\Dump\SubDump2\Screenshot.png" "SubDump2\Screenshot.png"
My Script is:
$directoryPath=$args[0]
Get-ChildItem $directoryPath -Recurse -Force | ForEach-Object -Process {
if (!$_.PSIsContainer) {"$($_.FullName -creplace '^[^\\]*\\', '') `t` $($_.Directory.Name)\$($_.Name)"}
}
Try PSCustomObject (and follow Quoting Rules):
Get-ChildItem $directoryPath -Recurse -Force -File |
ForEach-Object -Process {
[PSCustomObject]#{
fulln = """$($_.FullName -creplace '^[^\\]*\\', '')"""
shrtn = """$(Join-Path -Path $_.Directory.Name -ChildPath $_.Name)"""
}
}
Edit
To hide the column headings from the table, apply Format-Table cmdlet as follows (read more at Controlling column widths with Format-Table):
Get-ChildItem $directoryPath -Recurse -Force -File |
ForEach-Object -Process {
[PSCustomObject]#{
fulln = """$($_.FullName -creplace '^[^\\]*\\', '')"""
shrtn = """$(Join-Path -Path $_.Directory.Name -ChildPath $_.Name)"""
}
} | Format-Table -HideTableHeaders -AutoSize
However, Format- cmdlets are designed for console/screen output only. Read more in Problem with Format- cmdlets
Advanced script:
Param(
[Parameter(Position=0, Mandatory=$false, ValueFromPipeline)]
[string]$directoryPath='\bat\filez',
[Parameter()]
[switch]$AsObject
)
$outObj = Get-ChildItem $directoryPath -Recurse -Force -File |
ForEach-Object -Process {
[PSCustomObject]#{
fulln = """$($_.FullName -creplace '^[^\\]*\\', '')"""
shrtn = """$(Join-Path -Path $_.Directory.Name -ChildPath $_.Name)"""
}
}
if ( $AsObject.IsPresent ) {
$outObj | Out-Default
} else {
$outObj | Format-Table -HideTableHeaders -AutoSize
}
Example 1: .\SO\67514630.ps1
"bat\filez\more_real.eml" "filez\more_real.eml"
"bat\filez\PS_preferences.bat" "filez\PS_preferences.bat"
"bat\filez\Sample Input.eml" "filez\Sample Input.eml"
"bat\filez\SampleInput.eml" "filez\SampleInput.eml"
"bat\filez\folder\xxx.csv" "folder\xxx.csv"
Example 2: .\SO\67514630.ps1 \bat\foo.txt -AsObject
fulln shrtn
----- -----
"bat\files\676711\foo.txt" "676711\foo.txt"
"bat\files\bubu\foo.txt" "bubu\foo.txt"
"bat\Unusual Names\foo.txt" "Unusual Names\foo.txt"
"bat\foo.txt" "bat\foo.txt"

Copy everything except files on the list

I am trying to copy all files recursively from a:\ to b:\, except those whose metadata is present in a:\list.txt. The list.txt pattern is LastWriteTimeYYYY-MM-DD HH:MM:SS,size,.fileextension, for example:
2001-01-31 23:59:59,12345,.doc
2001-01-31 23:59:59,12345,.txt
2001-01-31 23:59:00,456,.csv
...so any and all files, anywhere in the a:\ dir tree, matching these metadata should not be copied.
I seem to be having trouble with the Where-Object in order to exclude the items on the list.txt, but copy everything else:
$Source = "C:\a"
$Target = "C:\b"
$List = Import-Csv list.txt -Header LastWriteTime,Size,Name
$Hash = #{}
ForEach ($Row in $List){
$Key = ("{0},{1},.{2}" -F $Row.LastWriteTime,$Row.Size,$Row.Name.Split('.')[-1].ToLower())
IF (!($Hash[$Key])) {$Hash.Add($Key,$Row.Name)}
}
$Hash | Format-Table -Auto
Get-Childitem -Path $Source -Recurse -File | Where-Object {$Hash -eq $Hash[$Key]}| ForEach-Object {$Key = ("{0},{1},{2}" -F ($_.LastWriteTime).ToString('yyyy-MM-dd HH:mm:ss'),$_.Length,$_.Extension.ToLower())
#$Key
If ($Hash[$Key]){
$Destination = $_.FullName -Replace "^$([RegEx]::Escape($Source))","$Target"
If (!(Test-Path (Split-Path $Destination))){MD (Split-Path $Destination)|Out-Null}
$_ | Copy-Item -Destination $Destination
}
}
I propose you a simplification of your code :
$Source = "C:\a\"
$Target = "C:\b\"
New-Item -ItemType Directory $Target -Force | Out-Null
$List = Import-Csv list.txt -Header LastWriteTime,Length,Extension
Get-Childitem $Source -Recurse -File | %{
$File=$_
$exist=$List | where {$_.LastWriteTime -eq $File.LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss') -and $_.Length -eq $File.Length -and $_.Extension -eq $File.Extension} | select -first 1
if ($exist -ne $null) {continue}
New-Item -ItemType Directory $File.DirectoryName.Replace($Source, $Target) -Force | Out-Null
Copy-Item $File.FullName $File.FullName.Replace($Source, $Target) -Force
}

Deleting a created file at every iteration

$getFiles = Get-ChildItem -Path $readDir -File -Include "*.doc","*.docx","*.xlsx"-Recurse | %{
if(($_ -match "\.doc$") -or ($_ -match "\.docx$")){
$Doc = $word.Documents.Open($_.fullname)
$nameDoc = $fileSaveLoc + $_.Name.Replace(".docx",".txt").replace(".doc",".txt")
$Doc.saveas([ref] $nameDoc, [ref] 5)
$Doc.close()
if((Get-ChildItem "I:\temp\").length -ne 0){
$locations = (Get-Item "I:\temp\"), (Get-ChildItem "I:\temp\" -Directory -recurse) | % {
Get-ChildItem -File $_.FullName | Select-String -List -Pattern '^\d{3}-?\d{2}-?\d{4}$' |
% Path
}
if($locations -ne $null){
$locations | out-file "I:\temp\SSN_FILES.txt"
#Get-ChildItem "I:\temp\" -exclude "fullpath.txt","SSN_FILES.txt" | remove-item
}else{
Get-ChildItem "I:\temp\" -exclude "fullpath.txt","SSN_FILES.txt" | remove-item
}
}
}
elseif($_ -match "\.xlsx$"){
$workbook = $excel.Workbooks.Open($_.FullName)
$csvFilePath = "I:\temp\" + $_.Name.Replace(".xlsx",".csv")
#$csvFilePath = $_.FullName -replace "\.xlsx$", ".csv"
$workbook.SaveAs($csvFilePath, [Microsoft.Office.Interop.Excel.XlFileFormat]::xlCSV)
$workbook.Close()
if((Get-ChildItem "I:\temp\").length -ne 0){
$locations = (Get-Item "I:\temp\"), (Get-ChildItem "I:\temp\" -Directory -recurse) | % {
Get-ChildItem -File $_.FullName | Select-String -List -Pattern '^\d{3}-?\d{2}-?\d{4}$' |
% Path
}
if($locations -ne $null){
$locations | out-file "I:\temp\SSN_FILES.txt"
#Get-ChildItem "I:\temp\" -exclude "fullpath.txt","SSN_FILES.txt" | remove-item
}else{
Get-ChildItem "I:\temp\" -exclude "fullpath.txt","SSN_FILES.txt" | remove-item
}
}
}
}
So this basically says:
check for a file matching doc/docx/xlsx
convert them into a file that can be parsed through
parse through each file at every iteration and compare it to a regex
if the regex is not null, then output it to a file with the file path
otherwise, delete it and anything else that was created except for two files
restart the process at the next file
Now the problem I am encountering is that the files aren't being deleted. I can't get them to be removed when they are created, when I know they don't match the regex. Setting ($locations -eq $true) doesn't solve that issue because it never goes into the first conditional statement.
The folder should contain only the two files that were created and possibly the ones that match the regex.

How to exclude directory in Get-ChildItem results?

My script is doing what I need it to do, but I would like to be able to exclude certain folders.
In this case, it would be \york\SedAwk\ and \york\_ROT\.
Now, if I only put one folder in the $exclude variable, it works as expected. It's when I put both (or more) that it excludes neither, and throws no errors either when running.
Here is the script:
param(
[string]$pattern,
[string]$path
)
$exclude = #('*\york\SedAwk\*','*\york\_ROT\*')
Get-ChildItem -path $path -Recurse -Filter *.html |
Where-Object{
ForEach-Object {
If (Get-Content $_.FullName | Select-String -Pattern "<h2>Stay Connected") {
Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<h2>Stay Connected" -Quiet
}
ElseIf (Get-Content $_.FullName | Select-String -Pattern "<h2>Soyez branch") {
Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<h2>Soyez branch" -Quiet
}
Else {
Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<\/main>" -Quiet
}
}
} |
Select Fullname | ?{$_.FullName -notlike $exclude}
And here is how I run it:
.\FindStringContent.ps1 -pattern "list-unstyled" -path "w:\test\york" | Export-CSV "C:\Tools\exclude.csv"
I don't like using the -Exclude parameter because it's not file/folder specific, if you have a file and a folder that matches the string you're excluding they'll both be excluded.
When i'm excluding files i exclude them based on the FullName property which you could put in your ForEach to check if any of the files is in your $exclude variable:
param(
[string]$pattern,
[string]$path
)
$exclude = 'SedAwk','_ROT'
Get-ChildItem -path $path -Recurse -Filter *.html |
Where-Object{$_.FullName -notlike $exclude -and ForEach-Object {
If ($exclude -notcontains $_.FullName) {
If (Get-Content $_.FullName | Select-String -Pattern "<h2>Stay Connected") {
Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<h2>Stay Connected" -Quiet
}
ElseIf (Get-Content $_.FullName | Select-String -Pattern "<h2>Soyez branch") {
Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<h2>Soyez branch" -Quiet
}
Else {
Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<\/main>" -Quiet
}
}
}
} | Select Fullname
Included suggested changes by TheMadTechnician

Replace multiple strings in a file using powershell

I am using following coe to replace the string
$folders=Get-ChildItem -Path "C:\temp\Database Scripts"
foreach($folder in $folders)
{
Write-Host $folder
$spath=[string]::Concat("C:\temp\Database Scripts\", $folder)
$subfolders=Get-ChildItem $spath
foreach($subfolder in $subfolders )
{
if($subfolder -match "Running Scripts")
{
$subfolerpath=[string]::Concat($spath,"\",$subfolder,"\*")
$files =get-childitem -Path $subfolerpath -include "AVEVAScripts*"
if($files -ne $null)
{
foreach( $file in $files)
{
Write-Host $file;
(Get-Content $file) | ForEach-Object {$_ -replace "DATABASE_USER","fhghjgj" `
-replace "DATABASE_PASSWORD", "DFGHFHJGJH" } |Set-Content $file
}
}
}
}
}
But ending up with following error.
Set-Content : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
Please help :)
Remove the $x in the end of Set-Content. $x is never declared.
Also, you could simplify it a lot. Ex:
Get-ChildItem -Filter "Running Scripts" -Path "C:\temp\Database Scripts" -Recurse | ForEach-Object {
Get-ChildItem -Path $_.FullName -Filter "AVEVAScripts*" -Recurse | ForEach-Object {
(Get-Content $_.FullName) | ForEach-Object {
$_ -replace "DATABASE_USER","fhghjgj" -replace "DATABASE_PASSWORD", "DFGHFHJGJH"
} | Set-Content $_.FullName
}
}
Or find all files that includes "AVEVAScripts" in it's name, then check if their full path includes "Running Scripts"
Get-ChildItem -Filter "AVEVAScripts*" -Path "C:\temp\Database Scripts" -Recurse |
Where-Object { $_.FullName -like "*Running Scripts*" } |
ForEach-Object {
(Get-Content $_.FullName) | ForEach-Object {
$_ -replace "DATABASE_USER","fhghjgj" -replace "DATABASE_PASSWORD", "DFGHFHJGJH"
} | Set-Content $_.FullName
}