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"
Related
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.
here is the script I've created. I have downloaded the 'PSSearch' package and when I goto commands 'Search-Index' is one of the available commands
$computers = #([some computer])
$destination = "[some path]"
foreach ($computer in $computers) {
$Path = Set-Location [path on computer]
$keywords= #('"word 1"','word2','word3','word4')
$dirlist = Get-ChildItem -Recurse -Force $Path -ErrorAction Continue
foreach($word in $keywords) {
$SearchResults = Search-Index $word
$dirlist | Where-Object {$_.Name -match $SearchResults} | Select-Object Name,FullName | format-Table * -AutoSize |
Export-Csv $destination\FoundFiles.csv -nti -Append
$cui = ($dirlist | Where-Object {$_.Name -match $SearchResults})
Copy-Item $cui -Destination $destination - Append
}
}
What is happening is I'm getting all files and folders from the location (not just the ones I'm searching for)
The problem could be that I don't know how this line should be scripted
$cui = ($dirlist | Where-Object {$_.Name -match $SearchResults})
I'm tying to automate gci in order to work on each row in a config file, where for each row I have as first column the path, and following it a list of files. Something like this:
C:\Users\*\AppData\Roaming\* *.dll
C:\Test file.txt,file2.txt
This means that gci will search for:
*.dll in C:\Users*\AppData\Roaming*
file.txt in C:\Test
file2.txt in C:\Test
In order to do this I'm creating dynamically the where condition in the script below. Here the ps script I'm using
foreach($line in Get-Content .\List.txt) {
try {
$path,$files = $line.split(' ')
$files = $files.split(',')
}
catch {
$path = $line
$files = "*.*"
}
if([string]::IsNullOrEmpty($files)){
$files = "*.*"
}
$filter = $files -join(" -or `$_.Name` -like ")
$filter = "`$_.Name` -like " + $filter
echo "Searching Path: $path, Pattern: $filter" | out-file -append -encoding ASCII -filepath .\result.txt
if ($path.Contains("*"))
{
gci -Path $path -Recurse | Where {$filter} | Select -ExpandProperty FullName | Out-String -Width 2048 | out-file -append -encoding UTF8 -filepath .\result.txt
}
else
{
gci -Path $path | Where {$filter} | Select -ExpandProperty FullName | Out-String -Width 2048 | out-file -append -encoding UTF8 -filepath .\result.txt
}
}
The problem is that the where filter is not considered. All files are returned
First attempt, suggested by
foreach($line in Get-Content .\List.txt) {
try {
$path,$files = $line.split(' ')
$files = $files.split(',')
}
catch {
$path = $line
$files = "*.*"
}
if([string]::IsNullOrEmpty($files)){
$files = "*.*"
}
$filter = $files -join(" -or `$_.Name -like ")
$filter = "`$_.Name -like " + $filter
$gciParams = #{
Path = $Path
Recurse = $Path.Contains('*')
}
"Searching Path: $path, Pattern(s): [$($files -join ',')]" | Add-Content -Path .\result.txt -Encoding ASCII
Get-ChildItem #gciParams | Where $filter | Select -ExpandProperty FullName | Add-Content -Path .\result.txt -Encoding UTF8
}
If you want to create a piece of code and defer execution of it until later, you need a Script Block.
A Script Block literal in PowerShell is just {}, so for constructing script block to filter based on a single comparison, you'd want to define $filter like this:
$filter = {$_.Name -like $filter}
At which point you can pass it directly as an argument to Where-Object:
Get-ChildItem $path |Where-Object $filter
... but since you want to test against multiple wildcard patterns, we'll need to write a slightly different filtering routine:
$filter = {
# Store file name of file we're filtering
$FileName = $_.Name
# Test ALL the patterns in $files and see if at least 1 matches
$files.Where({$FileName -like $_}, 'First').Count -eq 1
}
Since the $filter block now references $files to get the patterns, we can simplify your loop as:
foreach($line in Get-Content .\List.txt) {
try {
$path,$files = $line.split(' ')
$files = $files.split(',')
}
catch {
$path = $line
$files = "*.*"
}
if([string]::IsNullOrEmpty($files)){
$files = "*.*"
}
$gciParams = #{
Path = $Path
Recurse = $Path.Contains('*')
}
"Searching Path: $path, Pattern(s): [$($files -join ',')]" | Add-Content -Path .\result.txt -Encoding ASCII
Get-ChildItem #gciParams | Where $filter | Select -ExpandProperty FullName | Add-Content -Path .\result.txt -Encoding UTF8
}
Note that we no longer need to re-define $filter everytime the loop runs - the condition is based on the value of $files at runtime, so you can define $filter once before entering the loop and then reuse $filter every time.
The "trick" with using #gciParams (which allows us to remove the big if/else block) is known as splatting, but you could achieve the same result with Get-ChildItem -Path:$Path -Recurse:$Path.Contains('*') :)
I am trying to get the CSV output like below so that user can filter in excel.
Folder,Group,Permission
I:\Folder1,corp\group1,ReadData,ExecuteFile,Synchronize
I:\Folder1\Folder2,corp\group2,ReadData,ExecuteFile,Synchronize
Below is what is started with. Very inefficient and does not give the desired CSV output. Will appreciate any help.
$output_file = $(get-date -f MM-dd-yyyy_HH_mm_ss)+'.txt'
"{0},{1},{2}" -f "Folder","Groups","Permissions"| add-content -path $output_file
$file_content = ''
function GetFolders($path = $pwd)
{
if( $path -ne $null) {
$new_row = Get-ACL $path | select -ExpandProperty Access | Where-Object IdentityReference -Like "CORP*" | SELECT $path, IdentityReference, FileSystemRights | Format-Table -HideTableHeaders | Out-String
$fileContent += $new_row
$fileContent | add-content -path $output_file
foreach ($item in Get-ChildItem $path)
{
if (Test-Path $item.FullName -PathType Container)
{
Write-Output $item.FullName
GetFolders $item.FullName
$new_row = Get-ACL $item.FullName | select -ExpandProperty Access | Where-Object IdentityReference -Like "CORP*" | SELECT $item.FullName, IdentityReference, FileSystemRights | Format-Table -HideTableHeaders | Out-String
$fileContent += $new_row
$fileContent | add-content -path $output_file
}
}
}
}
GetFolders "J:\"
You were on the right path but went off-course a bit.
Set-Content -Path $FileName -Value 'Folder,Groups,Permissions'
(Get-Acl -Path $Path).Access |
Where-Object -Property IdentityReference -like 'corp*' |
ForEach-Object {
Add-Content -Path $FileName -Value "$Path,$($_.IdentityReference),$($_.FileSystemRights -replace '\s')"
}
To be a little more fancy (if you want to edit the code in the subexpressions or something of that nature)
$Val = {"$Path,$($_.IdentityReference),$($_.FileSystemRights -replace '\s')"}
... -Value (&$Val) ...
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