I'm hoping someone can help me here. I'm trying to make a Move-Item script where it will move all the "Music" folders into their parent directory unless the directory equals "C:\Temp\Users".
For example.. if the folder is located in "C:\Temp\Users\Billy Bob\Documents\Music" then the Music file will move to "C:\Temp\Users\Billy Bob\Music".
But if the "Music" folder is located at "C:\Temp\Users\Billy Bob\Music" then it won't be allowed to move as the "C:\Temp\Users" directory is specified within an "If-Statement" to block all moves into this directory.
This is what I have so far but I can't seem to get it to work for me
Get-ChildItem -Path C:\Temp\Users -Recurse -Directory -Force -Filter "Music"|
ForEach-Object {
if (Move-Item -Path $_.FullName -Destination $(Split-Path -Parent $_.PSParentPath) = C:\Temp\Users ) {
Write-Output "Move Stopped" -WhatIf
}
elseif (Move-Item -Path $_.FullName -Destination $(Split-Path -Parent $_.PSParentPath) -ne C:\Temp\Users) {
Move-Item -Path $_.FullName -Destination $(Split-Path -Parent $_.PSParentPath) -WhatIf
}
}
I have this part working but it moves all "Music" Folders to the Parent directory so I would like to add a condition to cancel any move where the destination of the move equals specifically "C:\Temp\Users". Any other destination would be okay to proceed to move the "Music" folder into the parent directory.
Get-ChildItem -Path C:\Temp\Users -Recurse -Directory -Force -Filter "Music"|
ForEach-Object {
Move-Item -Path $_.FullName -Destination $(Split-Path -Parent $_.PSParentPath) -WhatIf
}
CodePudding user response:
You don't need any condition if you start searching at a deeper level within the directory tree:
Get-ChildItem -Path C:\Temp\Users\*\*\* -Recurse -Directory -Force -Filter "Music" |
Move-Item -Destination { $_.Parent.Parent.FullName } -WhatIf
The wildcard part \*\*\*
forces Get-ChildItem
to enumerate directories which are at least three levels deeper than C:\Temp\Users
. So C:\Temp\Users\Billy Bob\Documents\Music
gets enumerated, but C:\Temp\Users\Billy Bob\Music
won't, because it only matches the first two *
from the wildcard path.
I've also simplified the Move-Item
call. You can pipe directly into Move-Item
, so it gets the -Path
parameter from the pipeline. For -Destination
you can pass a delay-bind script block ({ ... }
) argument, which makes ForEach-Object
obsolete (see this answer for further details).
Also, Split-Path -Parent
is not needed when working with DirectoryInfo
objects from Get-ChildItem
output. It has a .Parent
property which contains a DirectoryInfo
object as well, so by chaining you can get multiple levels up in the directory tree.