How to search a word in a file using PowerShell script - full-text-search

I have a list of 350 folders and each folder has a file Access log. I need to search all 350 files under all 350 folders for a name "Hound" and display the name of the folders which contain the name "Hound" in their access log file.
Below is my code, can someone help me with what should be added here to get the desired output, please?
#List all the folders in C:\testfolder
$folders = (Get-ChildItem -Path "C:\testfolder" | Where-Object{$_.Attributes -eq "Directory"} | Select Fullname)
#looping all folders
Foreach ($folder in $folders)
{
#Here I need to look for the word "Hound" inside the Access.log file and if the word is there, it should display the name of the $folder which has the word
}

Here's a fairly basic way to do this:
Get-ChildItem -Path d:\testfolder -Recurse | Select-String -Pattern "Hound"
If you need to make sure that only files called access.log are searched then specify a filter:
Get-ChildItem -Path d:\testfolder -Include "access.log" -Recurse | Select-String -Pattern "Hound"

Related

share multiple folders with the same name condition

I need everyone's help to get back to the power shell, I currently have a directory tree with a lot of folders you can see the images I borrowed.
enter image description here
I want to share folder "C and F" all directory tree at once with multiple users with view and edit permissions. hope everyone can help. I'm so stupid about this.
Hi khuchatvui and welcome to stackoverflow!
New-SmbShare can be used for creating shared folders.
If I understand correctly, you only want to share folders with a specific name that exist at multiple levels. SMB share names have to be unique, so that will provide a challenge if you want to have a specific sharename
You could partly automate this process by getting prompt for each folder name during the creation:
Solution 1 - prompt for name
$FoldersToShare = Get-ChildItem -Path C:\Tests\ -Recurse | Where-Object { $_.Name -eq 'F' -or $_.Name -eq 'C' } | Select-Object -ExpandProperty FullName
foreach ($folder in $FoldersToShare) {
New-SmbShare -Name (Read-Host -Prompt "Enter the sharename for $($folder)") -Path $folder -ChangeAccess "domain\groupname"
}
If there is no pattern in the folders you want to share, but the names are unique, you could make a list of all the folders you want to share like this:
Solution 2 - create unique folder names
Get-ChildItem -Path c:\tests -Directory -Recurse | Select-Object Name, FullName | Export-Csv -NoTypeInformation -NoClobber -Delimiter ';' -Path C:\Tests\Stackoverflow\FoldersToShare.csv
Then, modify that list using a text editor or Excel to only contain the folders you want to share and use that to loop through New-SmbShare
Finally, use PowerShell to import the contents of the modified csv file and loop through the entries with New-SmbShare to create the shared folders
$FoldersToShare = Import-Csv -Path C:\Tests\Stackoverflow\FoldersToShare.csv -Delimiter ';'
foreach ($folder in $FoldersToShare) {
New-SmbShare -Name $folder.Name -Path $folder.FullName -ChangeAccess "domain\groupname"
}
For my solution, I created the folder structure from your image under C:\Tests
C:\Tests\
A
A1
C
F
A2
C
B
B1
C
B2
C

Powershell Get-ChildItem wildcard in path?

Can a wildcard be put in a folder name mask? Or is it necessary to run Get-ChildItem twice, one for the direcdtories and a second for the path? Even with the code below, I'm getting no directories returned.
I think this post shows how to do it with the older syntax:
$folderName = "c:\BizTalk\Vendors\*\AS2FilesReceived\"
$folderMask = "$folderName\*.*"
$dirs = Get-ChildItem -Path $folderName -Recurse -Directory
Write-Host "Number of Matching Directories = $($dirs.Count)"
$dirs
#$files = $dirs | %{ Get-ChildItem -Path $folderMask -Filter "*.*" -Exclude "*997*.*" -File} | Where-Object {$_.CreationTime -gt (Get-Date).AddDays(-6)} | Sort-Object LastWriteTime -Descending
Get-ChildItem supports wildcards in the path, but the wildcard applies only to a single folder level, i.e. a pattern C:\foo\*\bar will find folders C:\foo\abc\bar and C:\foo\xyz\bar, but won't find a folder C:\foo\abc\xyz\bar. For the latter you need something like this:
Get-ChildItem 'C:\foo' -Filter 'bar' -Directory -Recurse
If you have just a single variable folder level and want only files from the given path (without recursion) you can do something like this:
Get-ChildItem 'C:\foo\*\bar\*' -File
If you also want all files in subfolders below bar use this:
Get-ChildItem 'C:\foo\*\bar' -File -Recurse
Assuming that you want to find and return info about all files in all AS2FilesReceived directories for each folder under Vendors, then this might help you...
#Find all AS2FilesReceived directories
$dirs= Get-ChildItem -Path 'C:\BizTalk\Vendors\*\AS2FilesReceived\' -Directory
#Return number of directories
"$($dirs.Count) directories found"
#Return list of directory names
$dirs | % {$_.Parent.Name}
#Return the full name of every text file under each directory
$dirs | % {Get-ChildItem -Path $_ *.txt} | % {$_.FullName}
Which returns...
3 directories found
Vendor1
Vendor2
Vendor3
C:\BizTalk\Vendors\Vendor1\AS2FilesReceived\Vendor1AS2File.txt
C:\BizTalk\Vendors\Vendor2\AS2FilesReceived\Vendor2AS2File.txt
C:\BizTalk\Vendors\Vendor3\AS2FilesReceived\Vendor3AS2File.txt
Ultimately, I just wanted the files, not sure if I had a typo or what, but now this works. It's possible I swithced from $folderMask to $folderName, or didn't have the *.* on the end of the $folderMask.
$folderMask = "c:\BizTalk\Vendors\*\AS2FilesReceived\*.*"
$files = Get-ChildItem -Path $folderMask -File
Write-Host "Number of Matching Files = $($files.Count)"

List 2 folders using a single command

Assume I have 2 folders A and B
Folder A contains files like "food.txt", "drinks.txt", ...
Folder B contains files like "beverage.txt", "entre.txt",...
Is there a way using dir (gci) or any command to get an output like
"beverage.txt", "drinks.txt", "entre.txt", "food.txt",..
Just use:
Get-ChildItem -File -Recurse | Select-Object -ExpandProperty Name
-File will list only files
-Recurse will also get all folder under the given one
Select-Object -Expandproperty Name will give you only the filename
If the files are located somewhere completely different you can just give GCImultiple Paths:
Get-ChildItem -File -Path "PathToFolderA","PathToFolderB" | Select-Object -ExpandProperty Name
The pre PSv3 way to check for file/directory is to inspect the PSIsContainer property in a Where-Object
So this line will return:
PS A:\> Get-ChildItem -Path "Folder A","Folder B" |Where-object {!$_.PSIsContainer}| Select-Object -ExpandProperty Name
drinks.txt
food.txt
beverage.txt
entre.txt
Taking your question literal with double quotes and separated with ,
(Get-ChildItem -Path "Folder A","Folder B" |Where-object {!$_.PSIsContainer}|ForEach-Object { '"{0}"' -f $_.Name}) -join ', '
"drinks.txt", "food.txt", "beverage.txt", "entre.txt"
To have output sorted, just insert a |Sort-Object Name
(Get-ChildItem -Path "Folder A","Folder B" |sort Name|Where-object {!$_.PSIsContainer}|ForEach-Object { '"{0}"' -f $_.Name}) -join ', '
"beverage.txt", "drinks.txt", "entre.txt", "food.txt"

Recursively Rename Files In All Subfolders Sequentially

I have a series of folders and subfolders, structured in this way:
001/Fabric/Blue/ (.jpg files, sequentially named)
001/Fabric/Green/ (.jpg files, sequentially named)
002/Fabric/Blue/ (.jpg files, sequentially named)
002/Fabric/Green/ (.jpg files, sequentially named)
etc.
The file names have excess string characters that I would like to remove, and I would like to convert their file names into an easier sequential format (0.jpg, 1.jpg, etc.).
I tried working with a few different PowerShell examples to get this to work. I have the recursive searching functionality working, however I receive an error about an InvalidOperationException when trying to rename the files in the ForEach-Object loop. Additionally, I am afraid my sequential numbering is not being 'reset' for each of the folders where it renames files.
$i = 0
Get-ChildItem -Filter "*.jpg" -Recurse | ForEach-Object {
Rename-Item $_ -NewName ('$i.jpg' -f $i++)
}
So, two questions:
How can I fix the error with Rename-Item?
How can I ensure my variable is reset for each subfolder the script starts renaming files in?
If you take a two step approach, first getting all the folders containing jpg's and then iterating through this list, you have no problem beginning with 1. But I'd always use leading zeroes for such a renumbering.
$BaseFld = "Q:\Test\"
$Ext = "*.jpg"
$jpgFolders = gci $($BaseFld+$Ext) -Recurse |
Select -ExpandProperty Directory -Unique |
select -ExpandProperty Fullname | Sort
ForEach ($Folder in $jpgFolders) {
Set-location $Folder
$i = 1
Get-ChildItem $Ext | %{Ren $_ -NewName ('{0:D4}.jpg' -f $i++) -whatif}
}
If the ouptut suits you, remove the -whatif in the second last line
other method
$rootdir="C:\temp"
gci $rootdir -Recurse -Directory | %{$i=1; gci $_.FullName -Recurse -File -Filter "*.jpg" | %{Ren $_.FullName -NewName ('{0}.jpg' -f $i++)} }

Delete All But The Newest File of Pattern In Each Subdirectory

Requirements:
Iterate through all folders and files in each directory
Delete all files in each subdirectory except for the newest one (contains filename time stamp) and has a specific filename pattern or instead copy the one file in each subdirectory that is the newest and that is preceded with LIVE_DATA. (There are other files in each subdirectory I wish to ignore).
Directory: AISI-301.0000000001006165.2015-08-24_23-57-46-1
File: LIVE_DATA_2015-08-24_23-57-51.413+0000.MCA
How can I iterate through all of the files recursively while doing comparisons between files in each subdirectory only? I don't want to compare all of them together. Just the one's inside each subdirectory.
for $filename in Get-ChildItem -recurse {
for $filename in $directory {
if ($filename > $filename2) {
$temp = $filename
}
$filename2 = $filename1
}
}
This is what I ended up using to rename my file's after the directory names. It appends the file name to the end and the directory name comes first. I hope this helps somebody else that might be searching for this solution.
Get-ChildItem -include *LIVE_DATA_*.MCA -recurse | Rename-Item -NewName { $_.Directory.Name+'_'+$_.Name}
If you want to remove all files LIVE_DATA_* except the most recent one on a per-folder basis you could do something like this:
$root = 'C:\path\to\root\folder'
Get-ChildItem $root -Recurse | ? { $_.PSIsContainer } | ForEach-Object {
Get-ChildItem (Join-Path $_.FullName 'LIVE_DATA_*') |
Sort-Object Name -Desc |
Select-Object -Skip 1 |
Remove-Item -Force
}
Get-ChildItem $root -Recurse | ? { $_.PSIsContainer } lists all subfolders of $root. Then the ForEach-Object runs another Get-ChildItem statement (without recursion) for each subfolder separately. The Join-Path statement builds a wildcard path from the filename pattern and the full path to the folder (C:\path\to\root\folder\sub\folder\LIVE_DATA_*).
Basically the code lists all folders, then processes the files for each individual folder.

Resources