1. You can now help support WorldwideDX when you shop on Amazon at no additional cost to you! Simply follow this Shop on Amazon link first and a portion of any purchase is sent to WorldwideDX to help with site costs.
    Dismiss Notice

PowerShell Ramblings

Discussion in 'Announcements & Open Forum' started by ButtFuzz, Oct 8, 2019.

  1. ButtFuzz

    ButtFuzz Anti-BS Advocate ● WO0WOO ● Reverend Doctor

    Joined:
    Aug 11, 2005
    Messages:
    557
    Likes Received:
    235
    No, 357Magnum, this is not about +P!

    I have a relatively robust music collection... mostly of filetypes .m4a and .mp3. There is one indispensable tool that I recommend to tag and rename a music collection and it does not run on Linux. The name of that tool is, strangely enough, mp3tag and you can give it a whirl here: https://www.mp3tag.de/en/ .

    This tool makes it a delight to properly tag your files, and I also use it to delete any files with bit rates < 320 Kbps. When I purge these 'inferior' files, I am often left with empty directories. These empty directories can be somewhat difficult to remove manually, and I sure don't want them to continue being backed up by my nightly backup processes... and I really don't want these empty directories to be indexed by my streaming music server software.

    So, as an exercise in futility I present 'try 0.1' at a PowerShell script to delete any directories in your production music collection containing no music files:

    ######################################################
    #Remove-FoldersIfNoMusic.ps1
    ######################################################
    ######################################################
    function Get-Today()
    {
        return get-date -Format yyyy-MM-dd
    }
    ######################################################
    ######################################################
    $tailRecursion = {
        param(
            $Path
        )
        $today = Get-Today
        $logfile = "C:\TEMP\$today-FolderRemovalLog.txt"
        foreach ($childDirectory in Get-ChildItem -Force -LiteralPath $Path -Directory) {
            & $tailRecursion -Path $childDirectory.FullName
        }
        $currentChildren = Get-ChildItem -Force -LiteralPath $Path
        $isEmpty = $currentChildren -eq $null
        if ($isEmpty) {
            Write-Verbose "Removing empty folder at path '${Path}'." -Verbose
            Add-Content "Removing empty folder at path '${Path}'." -Path $logfile
            Remove-Item -Force -LiteralPath $Path
        }
    }
    #
    # Call It like this:
    # & $tailRecursion -Path 'C:\a'
    ######################################################
    ######################################################
    <#
    If you want to test it here's code that will create interesting test data (make sure you don't already have a folder c:\a because it will be deleted):
    # This creates some test data under C:\a (make sure this is not
    # a directory you care about, because this will remove it if it
    # exists). This test data contains a directory that is hidden
    # that should be removed as well as a file that is hidden in a
    # directory that should not be removed.
    Remove-Item -Force -Path C:\a -Recurse
    New-Item -Force -Path C:\a\b\c\d -ItemType Directory > $null
    $hiddenFolder = Get-Item -Force -LiteralPath C:\a\b\c
    $hiddenFolder.Attributes = $hiddenFolder.Attributes -bor [System.IO.FileAttributes]::Hidden
    New-Item -Force -Path C:\a\b\e -ItemType Directory > $null
    New-Item -Force -Path C:\a\f -ItemType Directory > $null
    New-Item -Force -Path C:\a\f\g -ItemType Directory > $null
    New-Item -Force -Path C:\a\f\h -ItemType Directory > $null
    Out-File -Force -FilePath C:\a\f\test.jpg -InputObject 'Dummy file'
    Out-File -Force -FilePath C:\a\f\foo.mp3 -InputObject 'Dummy file'
    Out-File -Force -FilePath C:\a\f\h\hidden.jpg -InputObject 'Hidden file'
    Out-File -Force -FilePath C:\a\f\h\hidden.m4a -InputObject 'Hidden file'
    $hiddenFile = Get-Item -Force -LiteralPath C:\a\f\h\hidden.jpg
    $hiddenFile.Attributes = $hiddenFile.Attributes -bor [System.IO.FileAttributes]::Hidden
    $hiddenFile = Get-Item -Force -LiteralPath C:\a\f\h\hidden.m4a
    $hiddenFile.Attributes = $hiddenFile.Attributes -bor [System.IO.FileAttributes]::Hidden
    #Here's how you use it. Note that this will remove the top folder
    #(the C:\a folder in this example, which gets created if you generated the test data using the script above)
    #if that folder winds up being empty after deleting all empty folders under it.
    #>
    CLS
    $0dirfile = "C:\temp\0dirlist.txt"
    Clear-Content $0dirfile
    $ipath = (Read-Host "Please Enter The filepath to recurse and delete if no music files")
    $ipath = $ipath.trim()
    Add-Content $ipath -Path $0dirfile
    
    
    $1dirfile = "C:\temp\1dirlist.txt"
    Clear-Content $1dirfile
    $path=(Get-Content $0dirfile)
    $folders = Get-ChildItem $path -Recurse |where{$_.psiscontainer}|select -ExpandProperty fullname  #list all subfolders under the directory
    foreach($folder in $folders){
    $judge=Get-ChildItem $folder -Recurse |where {$_.fullname -like "*.m4a" -or $_.name -like "*.mp3"}  #filter the folders have music files
    if(!$judge){
    write-host "$folder has no music files"}
    add-content $folder -Path $1dirfile
    }
    
    #Don't boof the pooch!
    #Run a single recursion FIRST so as not to delete a folder of folders, you bonehead!
    
    $2dirfile = "C:\temp\2dirlist.txt"
    Clear-Content $2dirfile
    $noboofpaths = (Get-Content $1dirfile)
    ForEach ($path in $noboofpaths)
    {
    $folders = Get-ChildItem $path -Recurse |where{$_.psiscontainer}|select -ExpandProperty fullname  #list all subfolders under the directory
    foreach($folder in $folders){
    $judge=Get-ChildItem $folder -Recurse |where {$_.fullname -like "*.m4a" -or $_.name -like "*.mp3"}  #filter folders have music file
    if(!$judge){
    write-host "$folder has no music files"}
    add-content $folder -Path $2dirfile
    }
    }
    
    # Remove Secondary and Tertiary Directories containing no music.
    
    $path = ""
    $paths = ""
    $paths = (Get-Content $2dirfile)
    foreach ($path in $paths)
    {
    $path = $path.Trim()
    & $tailRecursion -Path $path
    }
    
    # Remove the rest! Bye-Bye!
    
    $path = ""
    $paths = ""
    $paths = (Get-Content $0dirfile)
    foreach ($path in $paths)
    {
    $path = $path.Trim()
    & $tailRecursion -Path $path
    }
    
    ######################################################
    ######################################################
    Change the file extensions to suit your liking.
    There will be 'warnings' the first time you run it because certain files do not exist yet.
    Log files, etc. are created @ C:\TEMP


     

  2. TM86

    TM86 Ooohhh, shiny!

    Joined:
    Jul 6, 2014
    Messages:
    361
    Likes Received:
    325
    You've built a lot of safeguards in there to make sure you don't accidentally remove things, and the logging is a nice touch. Good work!

    Sorry you have to deal with PowerShell, but at least you're making the best of it.
     
    357magnum likes this.
  3. 357magnum

    357magnum Sr. Member

    Joined:
    Feb 25, 2014
    Messages:
    1,678
    Likes Received:
    1,683
    Rob :whistle::LOL: , I know you are a Big Music Buff . But I wish it was + P I would have understood it better !;) All my vinyl is still in jackets , Cd's in plastic cases . So when I read about " Power Shell " It was Blah , Blah , Blah to me !:LOL: Dee's Truck has music loaded in , it has a USB plug ( I think ) how it got in that radio .... Damn if I know !:ROFLMAO:
     
    S&W357 likes this.
  4. ButtFuzz

    ButtFuzz Anti-BS Advocate ● WO0WOO ● Reverend Doctor

    Joined:
    Aug 11, 2005
    Messages:
    557
    Likes Received:
    235
    Non-exhaustive testing reveals try .1 SUCKS. So many safeguards and a few syntax errors guarantees it won't remove ANYTHING, much less granny from her rocker.

    v .02 coming right quick like....
     
  5. ButtFuzz

    ButtFuzz Anti-BS Advocate ● WO0WOO ● Reverend Doctor

    Joined:
    Aug 11, 2005
    Messages:
    557
    Likes Received:
    235
    Ok, here is version .00000000002. See original post for purpose.
    This one seems to mostly work!


    Code:
    ######################################################
    #Remove-FoldersIfNoMusic.ps1
    ######################################################
    ######################################################
    function Get-Today()
    {
        return get-date -Format yyyy-MM-dd
    }
    ######################################################
    ######################################################
    $tailRecursion = {
        param(
            $Path
        )
        $today = Get-Today
        $logfile = "C:\TEMP\$today-FolderRemovalLog.txt"
        foreach ($childDirectory in Get-ChildItem -Force -LiteralPath $Path -Directory) {
            & $tailRecursion -Path $childDirectory.FullName
        }
        $currentChildren = Get-ChildItem -Force -LiteralPath $Path
        $isEmpty = $currentChildren -eq $null
        if ($isEmpty) {
            Write-Verbose "Removing empty folder at path '${Path}'." -Verbose
            Add-Content "Removing empty folder at path '${Path}'." -Path $logfile
            Remove-Item -Force -LiteralPath $Path
        }
    }
    #
    # Call It like this:
    # & $tailRecursion -Path 'C:\a'
    ######################################################
    ######################################################
    <#
    If you want to test it here's code that will create interesting test data (make sure you don't already have a folder c:\a because it will be deleted):
    # This creates some test data under C:\a (make sure this is not
    # a directory you care about, because this will remove it if it
    # exists). This test data contains a directory that is hidden
    # that should be removed as well as a file that is hidden in a
    # directory that should not be removed.
    Remove-Item -Force -Path C:\a -Recurse
    New-Item -Force -Path C:\a\b\c\d -ItemType Directory > $null
    $hiddenFolder = Get-Item -Force -LiteralPath C:\a\b\c
    $hiddenFolder.Attributes = $hiddenFolder.Attributes -bor [System.IO.FileAttributes]::Hidden
    New-Item -Force -Path C:\a\b\e -ItemType Directory > $null
    New-Item -Force -Path C:\a\f -ItemType Directory > $null
    New-Item -Force -Path C:\a\f\g -ItemType Directory > $null
    New-Item -Force -Path C:\a\f\h -ItemType Directory > $null
    Out-File -Force -FilePath C:\a\f\test.jpg -InputObject 'Dummy file'
    Out-File -Force -FilePath C:\a\f\foo.mp3 -InputObject 'Dummy file'
    Out-File -Force -FilePath C:\a\f\h\hidden.jpg -InputObject 'Hidden file'
    Out-File -Force -FilePath C:\a\f\h\hidden.m4a -InputObject 'Hidden file'
    $hiddenFile = Get-Item -Force -LiteralPath C:\a\f\h\hidden.jpg
    $hiddenFile.Attributes = $hiddenFile.Attributes -bor [System.IO.FileAttributes]::Hidden
    $hiddenFile = Get-Item -Force -LiteralPath C:\a\f\h\hidden.m4a
    $hiddenFile.Attributes = $hiddenFile.Attributes -bor [System.IO.FileAttributes]::Hidden
    #Here's how you use it. Note that this will remove the top folder
    #(the C:\a folder in this example, which gets created if you generated the test data using the script above)
    #if that folder winds up being empty after deleting all empty folders under it.
    #>
    CLS
    $0dirfile = "C:\temp\0dirlist.txt"
    Clear-Content $0dirfile
    $ipath = (Read-Host "Please Enter The filepath to recurse and delete if no music files")
    $ipath = $ipath.trim()
    Add-Content $ipath -Path $0dirfile
    
    
    $1dirfile = "C:\temp\1dirlist.txt"
    Clear-Content $1dirfile
    $path=(Get-Content $0dirfile)
    $folders = Get-ChildItem $path -Recurse -Force | where {$_.psiscontainer} | select -ExpandProperty fullname  #list all subfolders under the directory
    foreach($folder in $folders){
    $judge=Get-ChildItem $folder -Recurse -Force | where {$_.name -like "*.m4a" -or $_.name -like "*.mp3"}  #filter if the folders have music files
    if(!$judge){
    write-host "$folder has no music files"
    add-content $folder -Path $1dirfile}
    }
    
    # List the individual files scheduled for removal.
    
    $2dirfile = "C:\temp\2dirlist.txt"
    Clear-Content $2dirfile
    $path = ""
    $paths = ""
    $paths = (Get-Content $1dirfile)
    foreach($path in $paths)
    {
        $path = $path.Trim()
        Remove-Item -Path $path -Recurse # -WhatIf
        Add-Content "Deleted $path" -Path $2dirfile
    }
    
    # Remove the all-falls! Bye-Bye!
    
    $path = ""
    $paths = ""
    $paths = (Get-Content $0dirfile)
    foreach ($path in $paths)
    {
    $path = $path.Trim()
    & $tailRecursion -Path $path
    }
    
    ######################################################
    ######################################################
     
  6. TM86

    TM86 Ooohhh, shiny!

    Joined:
    Jul 6, 2014
    Messages:
    361
    Likes Received:
    325
    Better than nuking your collection, or wiping the OS. Don't ask how I know.

    Just remember, doctors get to bury their mistakes. Coders have to support theirs forever.
     
    Shadetree Mechanic likes this.

Share This Page

  • About Us

    The WorldwideDX Radio Forum was originally established in 2001. We pride ourselves on welcoming Radio Hobby enthusiasts of all types, while offering unbiased, informative, and friendly discussion among the members. We are working every day to make sure our community is the best Radio Hobbyist's site.
  • Like us on Facebook

  • Premium VIP Member

    The management works very hard to make sure the community is running the best software, best designs, and all the other bells and whistles. Care to buy us a beer? We'd really appreciate it!

    Donate to us!