powershellexceptget-childitemfile-move

Powershell move folders with exclude


I have a lots of folders with contents that I want to move to another folder Below I want to move the 3 folders to the ARKIV folder - it works but the script crasches at the end. Am I using the Exclude flag the wrong way? If I use -Whatif it seems to want to move that folder as well - see picture 2

My code is as follows:

$current_logfiles = "H:\FAKTURA\"
$destination = "H:\FAKTURA\ARKIV\"
$excludes = "H:\FAKTURA\ARKIV\"

if ((Test-Path -Path $destination)) 
{
    Get-ChildItem -Exclude $excludes  -Path H:\FAKTURA  | Move-Item  -Destination 
    H:\FAKTURA\ARKIV -Whatif
}

enter image description here

enter image description here


Solution

  • Am I using the Exclude flag the wrong way?

    Yes:

    In your case, since you're not using -Recurse and are therefore only targeting the immediate child items of your input directory, the solution is to use the name only, i.e. $excludes = 'ARKIV':

    $excludes = 'ARKIV'
    Get-ChildItem -Exclude $excludes -Path H:\FAKTURA  | 
      Move-Item  -Destination H:\FAKTURA\ARKIV -Whatif
    

    Note: Due to a bug in Windows PowerShell, you must use -Path in the command above, even though -LiteralPath is conceptually appropriate and in general more robust.

    (The code could be simplified: you could use $destination with -Destination and (Split-Path -Leaf $destination) as the $excludes value.
    To skip items that are already present in $destination, insert the following pipeline segment before Move-Item:
    Where-Object { -not (Test-Path -LiteralPath (Join-Path $destination $_.Name)) })


    Recursive use cases currently not supported by -Exclude:

    It follows from the above that, when -Recurse is used:

    These limitations apply to Windows PowerShell and to PowerShell (Core) up to at least the version current as of this writing, v7.3.x.
    The next section links to feature requests that may provide this functionality in the future.

    Workarounds, based on post-filtering via Where-Object:

    In the simplest case, if the paths to exclude can be matched via wildcard expressions, use -notlike; e.g.:

    Get-ChildItem -Recurse -File -Filter *.txt |
      Where-Object FullPath -notlike Arkiv/* |
      Where-Object FullPath -notlike */sub/dir/* |
    

    This works for excluding the content of the directories of interest, but not these directories themselves (which isn't a problem in this example, given that -File is used to enumerate only files).

    While you could add another -notlike operation that omits the /* in order to also match the directories themselves (e.g., -notlike */sub/dir), such duplication is obviously cumbersome.
    An alternative is to use regexes with -notmatch instead:

    Get-ChildItem -Recurse -Directory |
      Where-Object FullPath -notmatch '(^|\\)node_modules(\\|$)'
    

    Potential future enhancements:

    There are two relevant feature requests to potentially overcome the limitations of -Exclude in the future: