find and recurse - powershell

I have a folder structure d:\domains\<domain>\folder1\folder2\folderx
There are maybe 20 <domain> folders, with differing levels of folders below them.
I want to search all folders for .php files, and just print the unique <domain> folders where they exit.
So for example, if there are files found in
d:\domains\domain1.com\test\test
d:\domains\domain2.com\test\test
d:\domains\domain2.com\test\help
I just want domain1.com,domain2.com to be printed. It needs to work in PowerShell v2.
I have the following, but it only prints the first domain?
Get-ChildItem -Path #(Get-ChildItem -Path D:\domains | Where-Object {$_.PSIsContainer})[1].FullName -Recurse *.php |
Select-Object -ExpandProperty FullName

Enumerate the domain folders, then filter for those of them that contain .php files.
Get-ChildItem 'D:\domains' | Where-Object {
$_.PSIsContainer -and
(Get-ChildItem $_.FullName -Filter '*.php' -Recurse)
}
If you have PowerShell v3 or newer you can use the -Directory switch instead of checking for $_.PSIsContainer:
Get-ChildItem 'D:\domains' -Directory | Where-Object {
Get-ChildItem $_.FullName -Filter '*.php' -Recurse
}
Select the Name property from the output if you want just the folder/domain names:
... | Select-Object -Expand Name

Related

Powershell Get-ChildItem extract username from profile folder

I have drive where roaming user profiles are stored:
U:\Users\john.doe
U:\Users\john.wick
U:\Users\john.smith
I need to check if users have files with *.pdf extensions stored in their profiles
$a = Get-ChildItem "U:\users\" -Include *.pdf -Recurse | select FullName
foreach ($b in $a){
Write-Output $b
}
Output
U:\Users\john.wick\desktop\file.pdf
U:\Users\john.wick\documents\a.pdf
U:\Users\john.doe\desktop\1.pdf
..................................
I need to write column to extract username from path, and one column with full file path.
How to do it ?
john.doe
john.wick
--------
Call Get-ChildItem without -Recurse to discover the profile folders, then use Where-Object + Get-ChildItem to find the ones containing pdfs:
$profilesWithPDFs = Get-ChildItem U:\Users\ -Directory |Where-Object { $_ |Get-ChildItem -File -Recurse -Filter *.pdf |Select -First 1 }
Once you've discovered the relevant folders, you can grab the name only:
$profilesWithPDFs |ForEach-Object -MemberName Name

Get ChildItem from only files of specific folders

I try to export files of specific named Folders:
Get-ChildItem -Path 'C:\Test' -Name -Recurse -File > C:\Test\Test.txt
I get a list like:
content.csv
Test.txt
Folder 1\INTERESTED_FOLDER\a - Kopie.txt
Folder 1\INTERESTED_FOLDER\a.txt
Folder 1\Neuer Ordner\ttt.txt
Folder 1\Neuer Ordner - Kopie\ttt.txt
Folder 2\INTERESTED_FOLDER\b - Kopie.txt
Folder 2\INTERESTED_FOLDER\b.txt
Folder 2\Neuer Ordner\ttt.txt
Folder 2\Neuer Ordner - Kopie\ttt.txt
But what i want is:
Folder 1\INTERESTED_FOLDER\a - Kopie.txt
Folder 1\INTERESTED_FOLDER\a.txt
Folder 2\INTERESTED_FOLDER\b - Kopie.txt
Folder 2\INTERESTED_FOLDER\b.txt
I tried with -Filter "INTERESTED" etc. but then i only get
C:\Test\Folder 1\INTERESTED_FOLDER
C:\Test\Folder 2\INTERESTED_FOLDER
What i do wrong?
If I read your question correctly, you want the FullNames of the files (so their names including the path).
If that is the case, remove the -Name switch and filter on the DirectoryName property like:
(Get-ChildItem -Path 'C:\Test' -Recurse -File |
Where-Object { $_.DirectoryName -match 'INTERESTED_FOLDER' }).FullName | # also matches 'MY_INTERESTED_FOLDER_123'
Set-Content -Path 'C:\Test\Test.txt'
Alternatives for the Where-Object clause:
# also matches 'MY_INTERESTED_FOLDER_123'
Where-Object { $_.DirectoryName -like '*INTERESTED_FOLDER*' }
or if you are looking for a precise match on the complete folder name
# does NOT match 'MY_INTERESTED_FOLDER_123'
Where-Object { $_.DirectoryName -split '[/\\]' -contains 'INTERESTED_FOLDER' }
You can perform a wildcard search using the -Filter parameter:
Get-ChildItem -Path 'C:\Test' -Name -Recurse -File -Filter *INTERESTED_FOLDER* > C:\Test\Test.txt
If for example, you were interested in finding the files in INTERESTED_FOLDER but also only the files that are .txt you could do:
-Filter *INTERESTED_FOLDER*.txt
Using the -Name parameter affects your capabilities because you are returning strings instead of FileInfoObjects. You may then use Where-Object to capture everything.
Get-ChildItem -Path 'C:\Test' -Name -Recurse -File |
Where {$_ -match '\\INTERESTED_FOLDER\\'} |
Set-Content c:\test\test.txt
Note that the matching above assumes INTERESTED_FOLDER is not a direct descendent of your path. If that is a possibility, then your match expression needs to be updated to \\?INTERESTED_FOLDER\\.

How to loop through all subfolders in a directory, and remove files with a specific filename

I am trying to write a script in Powershell to remove some files automatically with a certain file name.
My idea is to get all the folders in the directory, then loop through the subdirectory, and remove all items with the file name, but it doesn't seem to be working as expected.
Here is my script
$folders = Get-ChildItem -path "C:\Website-Backup" -Recurse | Where-Object {$_.PsIsContainer} |Group-Object {$_.FullName.Split('_')[0] }
$subfolders = Get-ChildItem -path $folders -Recurse | Where-Object {$_.PsIsContainer} | Group-Object {$_.FullName.Split('_')[0] }
ForEach($subfolder in $subfolders)
{
Remove-Item * -Include *100x*
}
Any idea why the script doesn't seem to be doing anything?
I think you can simplify your code if I understand correctly to:
Get-ChildItem "C:\Website-Backup" -Recurse -include "*100x*" -file | remove-item
The Group-Object command is likely what's confusing things here - Remove-Item is expecting a path - you're not referencing the subfolder variable in your loop as well, so this is the same as just running the Remove-Item command as many times as there are items in the array.
You can try this instead;
Get-ChildItem -Path "C:\Website-Backup" -Recurse | Where-Object -FilterScript { $_.name -like 'MyFile.txt' } | Remove-Item
This will pipe the returned child items into Where-Object, filter it to the specified file name, then pass that to Remove-Item as a file path.
You can also skip the Where-Object, but you lose a bit of control this way;
Get-ChildItem -Path 'C:\WebSiteBackup\*MyFile.txt' -Recurse | Remove-Item

Recursively Delete Files and Directories Using a Filter on the Directory Name

I am attempting to delete all directories, sub-directories, and the files contained in them based on a filter that specifies the required directory/sub-directory name.
For example, if I have c:\Test\A\B.doc, c:\Test\B\A\C.doc, and c:\Test\B\A.doc and my filter specifies all directories named 'A', I would expect the remaining folders and files to be c:\Test, c:\Test\B and c:\Test\B\A.doc respectively.
I am trying to do this in PowerShell and am not familiar with it.
The following 2 examples will delete all of the files that match my specified filter, but the files that match the filter as well.
$source = "C:\Powershell_Test" #location of directory to search
$strings = #("A")
cd ($source);
Get-ChildItem -Include ($strings) -Recurse -Force | Remove-Item -Force –Recurse
and
Remove-Item -Path C:\Powershell_Test -Filter A
I would use something like this:
$source = 'C:\root\folder'
$names = #('A')
Get-ChildItem $source -Recurse -Force |
Where-Object { $_.PSIsContainer -and $names -contains $_.Name } |
Sort-Object FullName -Descending |
Remove-Item -Recurse -Force
The Where-Object clause restricts the output from Get-ChildItem to just folders whose names are present in the array $names. Sorting the remaining items by their full name in descending order ensures that child folders get deleted before their parent. That way you avoid errors from attempting to delete a folder that had already been deleted by a prior recursive delete operation.
If you have PowerShell v3 or newer you can do all filtering directly with Get-ChildItem:
Get-ChildItem $source -Directory -Include $names -Recurse -Force |
Sort-Object FullName -Descending |
Remove-Item -Recurse -Force
I don't think you can do it quite that simply. This gets the list of directories, and breaks the path into its constituent parts, and verifies whether the filter matches one of those parts. If so, it removes the whole path.
It adds a little caution to handle if it already deleted a directory because of nesting (the test-path) and the -Confirm helps ensure that if there's a bug here you have a chance to verify the behavior.
$source = "C:\Powershell_Test" #location of directory to search
$filter = "A"
Get-Childitem -Directory -Recurse $source |
Where-Object { $_.FullName.Split([IO.Path]::DirectorySeparatorChar).Contains($filter) } |
ForEach-Object { $_.FullName; if (Test-Path $_) { Remove-Item $_ -Recurse -Force -Confirm } }

Rename-item in multiple subfolders

I have a piece of software which looks for a files named "report.txt". However, the text files aren't all named report.txt and I have hundreds of sub folders to go through.
Scenario:
J:\Logs
26-09-16\log.txt
27-09-16\report270916.txt
28-09-16\report902916.txt
I want to search through all the sub folders for the files *.txt in J:\logs and rename them to report.txt.
I tried this but it complained about the path:
Get-ChildItem * |
Where-Object { !$_.PSIsContainer } |
Rename-Item -NewName { $_.name -replace '_$.txt ','report.txt' }
Get-ChildItem * will get your current path, so in instead let's use the define the path you want Get-ChildItem -Path "J:\Logs" and add recurse because we want the files in all the subfolders.
Then let's add use the include and file parameter of Get-ChildItem rather than Where-Object
Then if we pipe that to ForEach, we can use the Rename-Item on each object, where the object to rename will be $_ and the NewName will be report.txt.
Get-ChildItem -Path "J:\Logs" -include "*.txt" -file -recurse | ForEach {Rename-Item -Path $_ -NewName "report.txt"}
We can trim this down a bit in one-liner fashion with a couple aliases and rely on position rather than listing each parameter
gci "J:\Logs" -include "*.txt" -file -recurse | % {ren $_ "report.txt"}
To replace certin word in all files in all sub folders
Get-ChildItem C:\Path -Recurse -Filter *OldWord* | Rename-Item -NewName { $_.name -replace 'OldWord', 'NewWord'} -verbose