Search code examples
powershellfilemovesubdirectory

Move files to subfolders if they match in Powershell etc?


I've googled for a while now but I'm unable to find any solution for this.

So I have a bunch of files in a folder, and in this folder I have subfolders.

I want to move those files to the subfolders if they match any of these.

Like this:

  • some random text yellow bananas more text.txt -> \yellow bananas
  • some other text red apples this is text.txt -> \red apples

Example - files:

  • Propulsion_mål_2020.jpg
  • Axevalla Vivid Wise As Goop.jpg
  • Dagens stjärna Cyber Lane.jpg
  • 640px Elian Web heat.jpg
  • ...

Example - directories:

  • Propulsion
  • Vivid Wise As
  • Cyber Lane
  • Vitruvio
  • ...

Target:

  • 1st file goes to 1st directory
  • 2nd file goes to 2nd directory
  • 3rd file goes to 3rd directory
  • 4th file match no directory and goes nowhere

Is it doable?

Btw, it's possible that more than one subfolder matches the filename. If so, it doesn't matter which subfolder the file is moved to.


Solution

  • here's one way to do the job ... [grin] there is nearly zero error checking or handling, so you may need to add that. nor is there any record of what was done/not-done.

    what it does ...

    • sets the constants
      all one of them. [grin]
    • creates the files & dirs to work with
      when you are ready to work with your own data, remove the entire #region/#endregion block.
    • gets a list of the dirs in the target location
    • creates a regex OR of the names of those dirs
    • gets a list of files in the target dir
    • iterates thru those files
    • tests for a match of the .BaseName property of each file against the dir name regex from earlier
    • if YES, creates a full dir name & moves the file
    • if NO, writes a warning to the warning stream
      that is on by default, so you otta see it when such a file is found.
    • finishes iterating thru the file list

    the code ...

    $SourceDir = "$env:TEMP\user3764769"
    
    #region >>> create some files & dirs to work with
    #    when ready to do this for real, remove this entire block
    if (-not (Test-Path -LiteralPath $SourceDir))
        {
        # the $Null suppresses unwanted "what was done" output
        $Null = New-Item -Path $SourceDir -ItemType 'Directory' -ErrorAction 'SilentlyContinue'
        }
    @'
    Propulsion_mal_2020.jpg
    Axevalla Vivid Wise As Goop.jpg
    Dagens stjarna Cyber Lane.jpg
    640px Elian Web heat.jpg
    '@ -split [System.Environment]::NewLine |
        ForEach-Object {
            $Null = New-Item -Path $SourceDir -Name $_ -ItemType 'File' -ErrorAction 'SilentlyContinue'
            }
    @'
    Propulsion
    Vivid Wise As
    Cyber Lane
    Vitruvio
    '@ -split [System.Environment]::NewLine |
        ForEach-Object {
            $Null = New-Item -Path $SourceDir -Name $_ -ItemType 'Directory' -ErrorAction 'SilentlyContinue'
            }
    #endregion >>> create some files & dirs to work with
    
    $DirList = Get-ChildItem -LiteralPath $SourceDir -Directory
    # the "|" is what regex uses for `-or`
    $RegexDL = $DirList.Name -join '|'
    
    $FileList = Get-ChildItem -LiteralPath $SourceDir -File
    
    foreach ($FL_Item in $FileList)
        {
        # the matched value is stored in $Matches[0]
        if ($FL_Item.BaseName -match $RegexDL)
            {
            $DirName = $Matches[0]
            $FullDirName = Join-Path -Path $SourceDir -ChildPath $DirName
    
            Move-Item -LiteralPath $FL_Item.FullName -Destination $FullDirName
            }
            else
            {
            Write-Warning ''
            Write-Warning (    'No matching directory was found for [ {0} ].' -f $FL_Item.Name)
            Write-Warning '    The file was not moved.'
            }
        } # end >>> foreach ($FL_Item in $FileList)
    

    output with one file that does not match any dir in the list ...

    WARNING: 
    WARNING: No matching directory was found for [ 640px Elian Web heat.jpg ].
    WARNING:     The file was not moved.