Reduce Nested Folders with empty parents

Hi All,

I’m looking for a way of finding out when there are child directories (however deep) which have only one folder and bringing them up one, (e.g. to save double clicking as well as reduce chance of >256 path name).

So I would like to basically identify when I have
Parent\Subfolder1\Subfolder2\subfolder3\test1.jpg
or
Parent\subfolder4\subfolder5\test2.jpg

and in those cases then pick the name of the lowest subfolder, bring it up to the top and delete the others
ending up with
Parent\subfolder3\test1.jpg
parent\subfolder5\test2.jpg

I know it sounds greedy to be adding this also to the question but…
In the case where you have
Parent\foo1\foo2\foo3\test1.jpg
Parent\foo1\foo2\foo3\test2.jpg
Parent\foo1\foo2\foo4\test3.jpg
then I would like to end up with
Parent\foo1\foo3\test1.jpg
Parent\foo1\foo3\test2.jpg
Parent\foo1\foo4.test3.jpg

Does this make sense? I’ve been trying it with a script but I end up tying myself a little into knots with nested ifs and repeated logic… where it feels like it could be more easily solved by doing some sort of recursive “uplevel” function which would start at the deepest level of the tree and keep stepping backwards until it has cleaned all the useless directories.
Thanks,

Gavin
PS: I’m not expecting someone to do all the work for me… I won’t really learn that way, but if you know how to solve the problem and can give me a few hints and tips I’ll try to work it out myself and then post the answer back!

Hey Gavin,
There is some conflicting information in your examples.

First you say, “I’m looking for a way of finding out when there are child directories (however deep) which have only one folder and bringing them up one”
Then you say, “in those cases then pick the name of the lowest subfolder, bring it up to the top and delete the others”

Bringing them up one and bringing them to the top are two different things.

In the example provided here, you are bringing to the top, not up one, since up one would result in the first line being Parent\Subfolder1\subfolder3\test1.jpg rather than Parent\subfolder3\test1.jpg. So that needs to be clarified.

Example provided in intial post

So I would like to basically identify when I have
Parent\Subfolder1\Subfolder2\subfolder3\test1.jpg
or
Parent\subfolder4\subfolder5\test2.jpg

End Result

Parent\subfolder3\test1.jpg
parent\subfolder5\test2.jpg

Then in this example, based on the requirement of “which have only one folder”, the result seems wrong. Only foo1 is a folder which only has 1 folder in it. foo2 has 2 folders in it.

Example provided in intial post

In the case where you have
Parent\foo1\foo2\foo3\test1.jpg
Parent\foo1\foo2\foo3\test2.jpg
Parent\foo1\foo2\foo4\test3.jpg

then I would like to end up with

Parent\foo1\foo3\test1.jpg
Parent\foo1\foo3\test2.jpg
Parent\foo1\foo4.test3.jpg

Based on the stated requirement it seems the result should be

Parent\foo2\foo3\test1.jpg
Parent\foo2\foo3\test2.jpg
Parent\foo2\foo4\test3.jpg

So some clarification needs to be made as to what you are trying to accomplish.

Curtis,

First of all thanks a lot for wading through my long question!
OK… if the CURRENT directory structure is as follows…
t:\downloads\GavinHoliday\DCIM\Folder1\IMG1.jpg
t:\downloads\GavinHoliday\DCIM\Folder1\IMG2.jpg
t:\downloads\GavinHoliday\DCIM\Folder2\IMG3.jpg
t:\downloads\GavinHoliday\DCIM\Folder2\IMG4.jpg
t:\downloads\BrianHoliday\Photos\Imported\DCIM2\20170101.jpg
t:\downloads\BrianHoliday\Photos\Imported\DCIM2\20170102.jpg
t:\downloads\SarahHoliday\Media\photo1.jpg
t:\downloads\SarahHoliday\Media\photo2.jpg

Then in effect the folders “DCIM”, Folder1, folder2, photos, Imported, DCIM2, Media … all of them add no value to me other than making the path longer and making me double click more. (ie, each is uniquely empty except for a childfolder which has “something in it”, {another useless subfolder or finally the images?} )

What I would want finally would be the following
t:\downloads\GavinHoliday\IMG1.jpg
t:\downloads\GavinHoliday\IMG2.jpg
t:\downloads\GavinHoliday\IMG3.jpg
t:\downloads\GavinHoliday\IMG4.jpg
t:\downloads\BrianHoliday\20170101.jpg
t:\downloads\BrianHoliday\20170102.jpg
t:\downloads\SarahHoliday\photo1.jpg
t:\downloads\SarahHoliday\photo2.jpg

Does this make more sense?
PS: I’m not looking for someone to give me the answer on a plate unless it’s actrually quite straightforward. If it’s a bit of a headache then just a hint in the right direction

I have a gut feeling that the answer may be in doing something like building a hashtable as a working list and then working backwards through it… here’s my first start.

function kickoff()
{
    $folderdepth = 0
    $currentdepth = 0
    $hopper = @{}
    $start = dir | where {$_.psiscontainer} | sort -Descending
    foreach ($folder in $start)
    {
        $dodive = checkdepth $folder.FullName
        Write-Output "do I do a dive further for folder $folder.name  .... $dodive"
        $hopper += @{$folder.fullname =  $currentdepth, $folderdepth, "yes"}
    }
    $hopper = $hopper.GetEnumerator() | Sort-Object Name
    return $hopper
}

function checkdepth ($deeper)
{
    $deeper = dir | where {$_.psiscontainer} | Measure-Object
    return $deeper.Count
}

function scratch ()
{
    $rubbish = @{1 = "Yes"}
    $rubbish
    $i = 0
    foreach ($item in $rubbish)
    {
    $i +=
    $rubbish += @{$i = "Yes"}
    $rubbish
    }
}

I’m thinking I would probably create a function that calls itself.

It would:

  1. look at the given directory path to see if there is only 1 child item
  2. check if that child item is a container
    3a If all that is true
    1. Move the contents of that directory to the parent directory
    2. Delete the directory
    3. Run the function against the given directory
      3b Else If the directory is empty
    4. Delete the directory
      3c Else If the directory has child directories
    5. Run the function against the child directories

or something to that effect.

Could you perhaps be making this a little harder than it needs to be?

Why not run this quick snippet for three difference folders, you could even do a variable with all the folder names and do a for each but this is just to get the point across:

gci t:\downloads\GavinHoliday\ -Recurse -Include "*.jpg" | move-item -Destination "t:\downloads\GavinHoliday"

Basically this is going to recursively go through your downloads\gavin folder find ALL of the jpg’s and then move then to GavinHolliday. If you have other file extension you want to move out then just do “.jpg",“”.gif” etc

If you really want to get fancy with it, you could do something like Curtis said with then checking for empty directories and deleting them.