2

I am looking for a PS script that checks for a certain file type(.err) in a folder's sub-folders (depth -1) and if it finds at least one file with the required file type, prints only the sub-folder's name, without file patch or file name, e.g.:

[root folder]
[subfolder1]-has .err in it
[subfolder2]-doesn't have .err in it
[subfolder3]-doesn't have .err in it
[subfolder4]-has .err in it
[subfolder5]-has .err in it

Output:

[subfolder1]
[subfolder4]
[subfolder5]

I'm not good at PowerShell, so I only found how to list subfolder names which has .err files in it as many times as it has files inside.

(Get-ChildItem -Path C:\root -Depth 1 -recurse -filter *.err).DirectoryName | echo
Nick
  • 4,820
  • 18
  • 31
  • 47
Rokask
  • 23
  • 2

3 Answers3

1

Okay, after direction from @mklement0 my suggestion would be,

(Get-ChildItem (C:\root + "\*\*") -Filter "*.err").Directory.Name | select -Unique
Karthick Ganesan
  • 375
  • 4
  • 11
  • 1
    Thank you. It's a quibble, because the performance difference probably won't matter here, but as a general point of interest: `Get-Unique` assumes pre-sorted input (or at least duplicates to be _grouped_, as in this case), which allows it to be much faster than `Select-Object -Unique`, which has to look at the entire input collection. Thus, along with pulling the `-Filter` argument into the wildcard path, I think the best formulation is ultimately: `(Get-ChildItem "C:\root\*\*.err").Directory.Name | Get-Unique` – mklement0 Aug 11 '19 at 17:39
0

If I understand the question properly, this should do what you want:

Get-ChildItem -Path 'C:\Root' -Depth 1 -Recurse -Filter *.err -File | 
    Group-Object -Property DirectoryName | 
    ForEach-Object { ($_.Name -split '\\')[-1] }

It searches 1 level deep through the subfolders and if it finds files with extension .err (no matter how many files are in that folder), it outputs the subfolder name only once.

If you are on PowerShell version below 3.0, change the top line into
Get-ChildItem -Path 'C:\Root' -Depth 1 -Recurse -Filter *.err | Where-Object { !$_.PSIsContainer } |

Theo
  • 57,719
  • 8
  • 24
  • 41
0

Update: Karthick Ganesan's answer is the simplest approach.


Try the following:

(Get-ChildItem -Depth 1 -Filter *.err).Directory.Name | Get-Unique | Select -Skip 1

For brevity, I've omitted the -Path argument and also the -File switch that limits matching to files, as it's fair to assume that you won't have any directories named *.err.

  • The use of -Depth implies the use of -Recurse, so the latter needn't be specified.

  • .Directory.Name outputs the matching files' directory names as an array (via member-access enumeration, PSv3+).

  • Get-Unique weeds out duplicates, which is necessary, because a given directory will be output multiple times if it contains multiple *.err files.

  • Select -Skip 1 (Select is a built-in alias for Select-Object) skips the first output object, because it represents the input directory itself (depth 0).

mklement0
  • 382,024
  • 64
  • 607
  • 775