Reduce Nested Folders with empty parents

This topic contains 5 replies, has 3 voices, and was last updated by  Jon 3 weeks ago.

  • Author
    Posts
  • #82946

    Gavin Williams
    Participant

    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!

  • #82958

    Curtis Smith
    Participant

    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.

  • #82960

    Gavin Williams
    Participant

    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

  • #82970

    Gavin Williams
    Participant

    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
        }
    }
    
  • #83063

    Curtis Smith
    Participant

    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
    1) Delete the directory
    3c Else If the directory has child directories
    1) Run the function against the child directories

    or something to that effect.

  • #83092

    Jon
    Participant

    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.

You must be logged in to reply to this topic.