madsantos
madsantos

Reputation: 27

Iterate through folders and check if a certain file exists

I was asked the following: Iterate through a list of folders, then iterate through a list of subfolders and finally check if there's a file named "can_erase.txt" on each subfolder. If the file exists, I must read it, save a parameter and delete the respective folder (not the main folder, but the subfolder which contains the file).

I started by using a for loop, but the names of the folders are random and I reached a dead end, so I thought I could use a foreach. Can anyone help me?

EDIT: My code is still pretty basic, since I know the names of the parent folders (they're named stream1, stream2, stream3 and stream4) but their subfolders are randomly named.

My current code:

For ($i=1; $i -le 4; $i++)
{
    cd "stream$i"
    Get-ChildItem -Recurse  | ForEach (I don't know which parameters I should use)
    {
        #check if a certain file exists and read it
        #delete folder if the file was present
    }
        cd ..
}

Upvotes: 2

Views: 5645

Answers (1)

Maximilian Burszley
Maximilian Burszley

Reputation: 19664

In this situation, you'll need multiple loops to get the stream folders, get those subfolders, then parse through all the files in the subfolders.

foreach ($folder in (Get-ChildItem -Path 'C:\streamscontainerfolder' -Directory)) {
    foreach ($subFolder in (Get-ChildItem -Path $folder -Directory)) {
        if ('filename' -in (Get-ChildItem -Path $subFolder -File).Name) {
            Remove-Item -Path $subFolder -Recurse -Force
            continue
        }
    }
}

The alternative to this is using the pipeline:

# This gets stream1, stream2, etc. added a filter to be safe in a situation where
# stream folders aren't the only folders in that directory
Get-ChildItem -Path C:\streamsContainerFolder -Directory -Filter stream* |
    # This grabs subfolders from the previous command
    Get-ChildItem -Directory |
        # Finally we parse the subfolders for the file you're detecting
        Where-Object { (Get-ChildItem -Path $_.FullName -File).Name -contains 'can_erase.txt' } |
        ForEach-Object {
            Get-Content -Path "$($_.FullName)\can_erase.txt" |
                Stop-Process -Id { [int32]$_ } -Force # implicit foreach
            Remove-Item -Path $_.FullName -Recurse -Force
        }

As a default, I'd recommend using -WhatIf as a parameter to Remove-Item so you can see what it would do.


Bonus after more thinking:

$foldersToDelete = Get-ChildItem -Path C:\Streams -Directory | Get-ChildItem -Directory |
    Where-Object { (Get-ChildItem -Path $_.FullName -File).Name -contains 'can_erase.txt' }
foreach ($folder in $foldersToDelete) {
    # do what you need to do
}

Documentation:

Upvotes: 4

Related Questions