Reputation: 165
I am trying to write a script that gathers a list of server names, then iterates through each server name and grabs the second to the newest folder in a directory, renames it, and copies it to another server. I am running into trouble with getting this to work all in one command, and I am not sure what is the best way to split it up and have it work properly. I get errors when trying different things, the main one is "rename-item: cannot evaluate parameter "NewName" because its argument is specified as a script block and there is no input". Here is the code snippet that causes this error:
$serverNames = Get-Content -Path "C:\servers.txt"
foreach ($serverName in $ServerNames) {
$reportServer = "a56741035"
Get-ChildItem "\\$($serverName)\d$\mposlogs\device" | where { $_.PSIsContainer } | Sort CreationTime -Descending | Select -Skip 1 | Select -First 1 | Rename-Item -NewName { "$serverName" + "_" + $_.Name } | Copy-Item $_.FullName -Destination "\\$($reportServer)\c$\temp\mpos\logs" }
Another is "cannot bind argument to parameter 'Path' because it is null". Here is the code that causes this error:
$serverNames = Get-Content -Path "C:\servers.txt"
foreach ($serverName in $ServerNames) {
$reportServer = "a56741035"
Get-ChildItem "\\$($serverName)\d$\mposlogs\device" | where { $_.PSIsContainer } | Sort CreationTime -Descending | Select -Skip 1 | Select -First 1 | ForEach-Object { Rename-Item -NewName { "$serverName" + "_" + $_.Name } | Copy-Item $_.FullName -Destination "\\$($reportServer)\c$\temp\mpos\logs" } }
I feel like I am very close, and just don't see something. Any assistance is greatly appreciated, thank you so much. Have a great day.
EDITED TO INCLUDE NEWEST CODE:
Get-ChildItem "\\$($serverName)\d$\mposlogs\device" | where { $_.PSIsContainer } | Sort CreationTime -Descending | Select -Skip 1 | Select -First 1 | ForEach-Object { Rename-Item -Path $_.FullName -NewName ( "$serverName" + "_" + $_.Name ) ; Copy-Item $_.FullName -Destination "\\$($reportServer)\c$\temp\mpos\logs" }
CODE FOR NEWEST COMMENTS:
Get-Child-Item "\\$serverName\d$\mposlogs\device" | where {$_.PSIsContainer} | Sort CreationTime -Descending | Select -Skip 1 | Select -First 1 | ForEach-Object { Rename-Item -Path $_.FullName -NewName ( "$serverName" + "" + $.Name ) ; Copy-Item ( "$serverName" + "" + $.Name ) -Destination "\\$reportServer\c$\temp\mpos\logs" }
Upvotes: 2
Views: 9577
Reputation: 2718
So this turned out to be more difficult than I thought it would be, the trick being that Rename-Item seems to basically consume the pipelined object without giving you a chance to use that object in the subsequent name(using a scriptblock is also not really ideal, much easier to use a simple concatted string) so you need to change the Rename-Item
portion of your loop slightly to
Rename-Item -Path $_.FullName -NewName ("$serverName" + "_" + $_.Name)
As far as the syntax changes prageeth suggests you can make them but they are unneeded and imo increase ambiguity(Get-Childitem does not require an escape character to access an admin share and there is nothing wrong with using $($) syntax even when not accessing a property).
EDIT
Ok after working in the comments for a bit here is an updated version of the full GCI pipeline. I tested it successfully in my environment so fingers crossed it works for you. Please let me know if any part of it doesn't make sense.
Get-ChildItem "\\$serverName\d$\mposlogs\device" | where {$_.PSIsContainer} | Sort CreationTime -Descending | Select -Skip 1 | Select -First 1 | ForEach-Object { Rename-Item -Path $_.FullName -NewName ( "$serverName" + "_" + $_.Name ) -PassThru | Copy-Item -Destination "\\$reportServer\c$\temp\mpos\logs" }
Upvotes: 5
Reputation: 8650
In situation like this is always best to analyse the command output first...
# Rename doesn't output anything by default
Rename-Item ToBeRenamed.txt Renamed.txt
# For most commands with that default behaviour, you can use -PassThru to force output
Rename-Item ToBeRenamed.txt Renamed.txt -PassThru
# Once we have something in the pipeline, we can pipe result to Copy-Item
Rename-Item ToBeRenamed.txt Renamed.txt -PassThru | Copy-Item -Destination C:\temp
ls C:\temp\Renamed.txt
I would recommend avoiding ForEach-Object here - it's not really needed. You just need to control output from commands, that's it.
Upvotes: 1
Reputation: 1063
Edit:
As user mike mentioned, it appears that admin shares doesn't need $ to be escaped with. The real problem is rename-Item cmdlet missing the -Path parameter. Thanks for bringing that up Mike!
However I still recommend removing the extra $ over $($serverName) to reduce ambiguity.
Try this!
Get-ChildItem "\\$serverName\d$\mposlogs\device" | where { $_.PSIsContainer } | Sort CreationTime -Descending | Select -Skip 1 | Select -First 1 | ForEach-Object { Rename-Item -Path $_.FullName -NewName { "$serverName" + "_" + $_.Name } | Copy-Item $_.FullName -Destination "\\$reportServer\c$\temp\mpos\logs" } }
Upvotes: 0