Forgive me but i am VERY new to Powershell, i.e. this is the first script I've ever tried to write. I want to move files from sub-directories of the folder \Export on one drive, to the same folder name on a network drive location. I'm using my local drive for both locations in the test (-WHatIf) example below but i was trying as a test something like;
$_SourcePath = "C:\exports"
$_dest = "c:\temp\exports\"
$_FileType= @("*.xml")
# Get all files and group by base name
$_command = Get-ChildItem -recurse ($_sourcePath) -include ($_FileType) | Where-Object {$_.CreationTime -lt (Get-Date).AddMinutes(-5)} | ForEach-Object {
"move-Item -Path $($_sourcepath)\$($_.Directory.Name)\$($_.Name) -Destination $($_dest)$($_.Directory.Name)\$($_.Name) -WHatif" }
$_command | ForEach-Object { $_
Invoke-Expression $_command }
so the script should (eventually once I've removed the -WhatIf) move all .xml files from \export\folder, \export\folder2 etc. into temp\export\folder1, temp\export\folder2 etc. whilst retaining the same filenames.
The issue is that the -destination object will not take the (what looks like a valid) string value being passed into it. I'm sure there's 1001 other ways to do this, but having tried several, I'm now at the sum extent to my Googling & knowledge skills. Thanks all.
CodePudding user response:
When I run your code as written, I get this error:
Invoke-Expression : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Command'.
This is because Invoke-Expression
needs to take $_
as its argument in order to run each command.
When correcting that problem, I then ran into the issue of the target directory not existing - but I'm sure you've already created your target directory C:\temp\exports
?
It is possible to reduce your code further by simply having the Move-Item -WhatIf
command run inside the first loop, meaning there's no need to build a list of commands to run with invoke-expression
- however I can see the benefit of generating a list of commands should you wish to log them somewhere or review them before executing (but the -WhatIf
sort of provides that functionality). Here's the single loop version:
$_SourcePath = "C:\exports"
$_dest = "c:\temp\exports\"
$_FileType= @("*.xml")
# Get all files and group by base name
Get-ChildItem -recurse ($_sourcePath) -include ($_FileType) | `
Where-Object {$_.CreationTime -lt (Get-Date).AddMinutes(-5)} | `
ForEach-Object {
move-Item -Path "$_.FullName" `
-Destination "$($_dest)$($_.Directory.Name)\$($_.Name)" `
-WHatif
}
Other changes:
- Wrapped paths in quotes to avoid paths-with-spaces issues
- Changed the input path in
Move-Item
to$_.FullName
as theGet-ChildItem
command provides the full path property as part of its output - Added some backticks to split long commands over lines
- Removal of
$_command
variable - no longer required