Array with Commands - powershell

I have a list of files which I would like to move to other destinations. Issues:
Destination is different
Errors can occur, e.g. File does already exist in Destination.
If so, I would like to delete the existing file (e.g. $StartM\C\A.Lnk)
How can I do this with a list / foreach or other possibility?
Move-Item -Path "$StartM\C\A.Lnk" -Destination "$StartM\Maintenance"
Move-Item -Path "$StartM\C\B.Lnk" -Destination "$StartM"

The canonical way of dealing with a situation like that is to define a mapping between sources and destinations:
$shortcuts = #{
"$StartM\C\A.Lnk" = "$StartM\Maintenance"
"$StartM\C\B.Lnk" = "$StartM"
}
and then process that mapping like this:
foreach ($src in $shortcuts.Keys) {
Remove-Item $shortcuts[$src] -Force -EA SiltenlyContinue
Move-Item $src -Destination $shortcuts[$src]
}

Thank you Ansgar. I got some issues:
1. Remove-Item:
The Argument can not be bound with the Parameter "Path", because it is an empty string.
CategoryInfo: InvalidData: (:) [Remove-Item], ParameterBindingValidationException
FullyQualifiedErrorId: ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.RemoveItemCommand
2. Move-Item:
No position parameter was found, which accept the argument "\Maintenance"
May be there is a missunderstanding. Source should be deleted if exists in Destination. E.g.: "$StartM\C\A.Lnk" = "$StartM\Maintenance".
Goal: "$StartM\C\A.Lnk" should be deleted if "A.Lnk" exists in "$StartM\Maintenance\A.Lnk".
Move-Item $src = $shortcuts[$src]
CategoryInfo: InvalidArgument: (:) [Move-Item], ParameterBindingException
FullyQualifiedErrorId: PositionalParameterNotFound,Microsoft.PowerShell.Commands.MoveItemCommand
3. ErrorAction
Remove-Item: The Parameter "ErrorAction" can not be bound. Type "SiltenlyContinue" can not be converted in type "System.Management.Automation.ActionPreference" ...
I just changed "-EA" ... -Force -EA SilentlyContinuefrom to "-Error Action". This type of Error has gone.
4. Double keys
If there are some constelations in the array like this:
"$StartM\C\B.Lnk" & "$End\C\B.Lnk" I got an error that double keys are not allowed in Hashliterals.
CategoryInfo : InvalidOperation: (System.Collections.Hashtable:Hashtable) [], RuntimeException
FullyQualifiedErrorId : DuplicateKeyInHashLiteral

Related

PowerShell script to set "date created" to specific times according to a csv file

I have some thousands of files in a folder that I need to bulk edit their creation time to a specific order.
I have prepared a csv file with all file names and the preferred creation times, like this:
filename;filecreationTime;
file1.mp4;10/11/2022 2:50;
file2.mp4;10/11/2022 2:49;
file3.mp4;10/11/2022 2:49;
etc
I have used this suggestion to a similar previous question: https://stackoverflow.com/a/36348448/20467894 and created a code like this:
Set-Location 'path to files'
Import-Csv -Path 'path to csv file' |
ForEach-Object { (Get-Item $_.filename).CreationTime = (Get-date $_.filecreationTime) }
The outcome is this error, for each line of the csv:
Get-Item : Cannot bind argument to parameter 'Path' because it is null.
At line:2 char:32
+ ForEach-Object { (Get-Item $_.filename).CreationTime = (Get-date ...
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetItemComm
and
What am I doing wrong?
EDIT: After Theos' comment, it run once in a sample subset of my files but never run again. Now it can indeed read the filenames, but it brings a new error:
Get-date$_.filecreationTime : The term 'Get-date$_.filecreationTime' is not recognized as the name of a cmdlet, functio
n, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is
correct and try again.
At line:2 char:57
+ ... (Get-Item $_.filename).CreationTime = (Get-date$_.filecreationTime) }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-date$_.filecreationTime:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Thanks everyone for your suggestions.
As pointed out by Theo, the problem was that in my language and regional formats the delimiter of the csv files is set to ";" instead of ",", as the latter is used as decimal...
So I had to insert an additional argument into the import csv (that was not obvious by the error expression), in order to clarify the non default delimiter:
-Delimiter ';'
So, the correct code for me was the following:
Set-Location 'path to files'
Import-Csv -Delimiter ';' -Path 'path to csv file' |
ForEach-Object { (Get-Item $_.filename).CreationTime = (Get-date $_.filecreationTime) }

Powershell Copy-item fails on unc path with space and ampersand

I am trying to use the powershell Copy-Item command to copy a file to a UNC Path.
Unfortunately, the UNC path on this production server has both spaces and an ampersand in the name.
I've tried a bunch of things, but haven't had any luck yet.
Could you please suggest a way to resolve this issue.
$InvokeExpressionPath = "\\servername\This Folder Has Spaces & Ampersand\Folder"
$TransfersSharePath = Invoke-Expression $InvokeExpressionPath
$TransfersSharePathFile = $InvokeExpressionPath + "\" + $FileName
Copy-Item -Path $CheckFileExists -Destination $TransfersSharePathFile -Force -ErrorAction SilentlyContinue
This is the error message that I get:
Invoke-Expression : At line:1 char:41
+ \\servername\This Folder Has Spaces & Ampersand\Folder
+ ~
The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double quotation marks ("&") to pass it as part of a string.
At E:\Scripts\CopyFile_Test.ps1:33 char:27
+ $TransfersSharePath = Invoke-Expression $InvokeExpressionPath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Expression], ParseException
+ FullyQualifiedErrorId : AmpersandNotAllowed,Microsoft.PowerShell.Commands.InvokeExpressionCommand
If I try to wrap the ampersand in double-double quotes (""&""), I get this error when the code runs.
\\servername\This : The term '\\servername\This' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At line:1 char:1
+ \\servername\This Folder Has Spaces "&" Ampersand\Folder
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (\\servername\This:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
DEBUG: This is the value of TransfersSharePathFile - \\servername\This Folder Has Spaces & Ampersand\Folder\file.zip
Copy-Item : Illegal characters in path.
At E:\Scripts\CopyFile_Test.ps1:36 char:5
+ Copy-Item -Path $CheckFileExists -Destination $TransfersSharePathFile -Force ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.CopyItemCommand
Thanks in advance for your help.
Thanks very much to AdamL and dread1 for their help. I used both suggestions.
For reference, this is what the working code now looks like.
$InvokeExpressionPath = "\\servername\This Folder Has Spaces & Ampersand\Folder"
$TransfersSharePathFile = Join-Path -Path $InvokeExpressionPath -ChildPath $FileName
$TransfersSharePathFile = $InvokeExpressionPath + "\" + $FileName
Copy-Item -Path $CheckFileExists -Destination $TransfersSharePathFile -Force -ErrorAction SilentlyContinue
Ampersand or spaces in path are not the problem. You're trying to use Invoke-Expression supplying path as parameter, which is not a valid command. Get rid of $TransfersSharePath line and use what's in $InvokeExpressionPath directly. Just change double quotation marks to single just in case. Also I suggest you create path using Join-Path instead of contatenating the strings.
Try:
$InvokeExpressionPath = '\\servername\This Folder Has Spaces & Ampersand\Folder'
Should do the job

'Rename-Item' makes a copy with the new name

Trying to make a script to backup specific folders and then rename the GUID key for the target user under HKLM...\ProfileLists but the rename-item command makes a copy of the key and creates a new key with the appended name though having full access
Tried with -force, tried with move-item instead of rename but it gives the exact same results, a new identical key as original but with an appended name
if ((Test-Path $FULLPATH)) {
Rename-Item $FULLPATH -NewName "$SSID.bak" -Force
if ($?) {
Write-Host "$USERNAME was SUCCESSFULLY renamed in the registry"
}
}
Expected result is to only rename the GUID-key in the registry.
Actual result is a duplicate key with the new duplicate to have the correct appended name.
Rename-Item : The registry key at the specified path does not exist.
At line:9 char:5
+ Rename-Item $FULLPATH -NewName "$SSID.bak" -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (HKEY_LOCAL_MACH...\folderredirect:String) [Rename-Item], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Object reference not set to an instance of an object.
At line:9 char:5
+ Rename-Item $FULLPATH -NewName "$SSID.bak" -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Rename-Item], NullReferenceException
+ FullyQualifiedErrorId : System.NullReferenceException,Microsoft.PowerShell.Commands.RenameItemCommand
The key does exist and I can run the same command again as proof (due to the test-path).
Verbose output do confirm its copying
VERBOSE: Performing the operation "Copy Key" on target "the key in question"
It works for me. Are your variables set in this way?
$SSID = 'S-1-5-21-1212123708-1212126490-1212120831-1001'
$FULLPATH = 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\S-1-5-21-1212123708-1212126490-1212120831-1001'
rename-item $fullpath -newname "$SSID.bak"
I was unable to rename the keys with rename-item with full paths and not using variables either. However resolved it by replacing rename-item to
# Rename the Registry profile
if ((Test-Path $FULLPATH)) {
reg copy "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$SSID" "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$SSID-$(Get-Date -f yyy-MM-DD)" /s /f
if (( $? -eq 'True' )) {
reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$SSID" /f
}
if (( $? -eq 'True' )) {
Write-Host "$USERNAME was SUCCESSFULLY renamed in the registry"
}
had to use half the full path in the reg copy/delete commands as the syntax is different (no colon). This worked

Copy-Item: Illegal characters in path

I'm trying to create a powershell script that will copy files from a source to the same path on multiple destination machines. I found this on the web and have pointed toward my test data, however, I continue to receive the following error (for each system it finds in the pc_list.txt).
Script:
$Computers = gc "C:\Temp\Script\PC_List.txt"
$Source = "C:\Temp\Script\AAAAA.txt"
$Destination = "C$\Temp\"
foreach ($Computer in $Computers) {
Copy-Item -Path $Source -Destination "\\$Computer\$Destination\" -Recurse
}
Error:
Copy-Item : Illegal characters in path.
At line:4 char:36
+ ... Computers) {Copy-Item $Source -Destination "\\$Computer\$Destination\ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.CopyItemCommand
PC Names in PC_List.txt:
DEPT-PC1
DEPT-PC2
DEPT-PC3
Can someone point me in the right direction?
BenH is correct. While I did not have any blank lines in the PC_List.txt, I did have a space at the end of each line... Great catch!!!
Now I’m getting “The target account name is incorrect”.
I’m thinking I’m going to need to add a $session credentials line but will need to figure out how to implement that piece...

Trying to use built-in PS1 methods Get-Date, Convert-Path, rename-item getting errors

I am new to PowerShell and trying to write my first script to copy files from one directory to another and then rename the files in the $DESTINATION directory once they are copied over there.
I am executing the script below from C:\Scripts directory on my machine.
The first foreach loop works great and my files land in the $DESTINATION.
But when I to through the 2nd loop I get the errors below
Any help/direction would be appreciated. Thanks.
Here is my code:
# Define variables.
$Source = "C:\ETLFILES\WinSCP\FilesETL\*.*"
$Destination = "C:\ETLFILES\WinSCP\SFE_Archive\"
$DestinationFiles = "C:\ETLFILES\WinSCP\SFE_Archive\*.*"
# Create the $sourceFileList variable to loop through
$sourceFileList = Get-ChildItem -path $Source
# Loop through the $soureFileList and copy the items to the $Destination.
foreach ($item in $sourceFileList) {
Copy-Item -Path $Source -Destination $Destination
}
# Create the $destinationFileList variable to loop through
$destinationFileList = Get-ChildItem -path $DestinationFiles
# Loop through the $destinationFileList and rename the files with appended DateTime stamp.
foreach ($itemDest in $destinationFileList) {
$Date = (Get-Date).ToString("yyyyMMdd_HHmmss")
$newFileName = $Date + "_" + $itemDest
Rename-Item $itemDest $newFileName
}
Here are the errors I'm getting and I think that I need to change the -path as it is looking to where the script is executing from and not looking at the $DestinationFiles directory like it looked to the $Source above:
PS C:\Scripts> C:\Scripts\ArchiveSFE_files.ps1
Rename-Item : Cannot rename the specified target, because it represents a path or device name.
At C:\Scripts\ArchiveSFE_files.ps1:21 char:5
+ Rename-Item $itemDest $newFileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Cannot rename the specified target, because it represents a path or device name.
At C:\Scripts\ArchiveSFE_files.ps1:21 char:5
+ Rename-Item $itemDest $newFileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Cannot rename the specified target, because it represents a path or device name.
At C:\Scripts\ArchiveSFE_files.ps1:21 char:5
+ Rename-Item $itemDest $newFileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Cannot rename the specified target, because it represents a path or device name.
At C:\Scripts\ArchiveSFE_files.ps1:21 char:5
+ Rename-Item $itemDest $newFileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
PS C:\Scripts>
PowerShell can be a bit tricky if you're used to text-based languages and tools, because everything in PowerShell is a .NET object.
This line:
$newFileName = Get-Date + "_" + $item # .ToString("yyyyMMdd-HHmmss") + "_" + $item
will most certainly result in an error. Get-Date returns a [datetime] object.
Although [datetime] does support the + operator, it expects an argument of the type [timespan] - and the string "_" can't be converted to a timespan.
What you want is a string representing the current date. Either use the ToString() statement that you've commented out, or use the -Format parameter to produce a formatted string instead of a [datetime] object:
$newFileName = (Get-Date).ToString("yyyyMMdd-HHmmss") + "_" + $item
or
$newFileName = (Get-Date -Format "yyyyMMdd-HHmmss") + "_" + $item
I'm not a betting man, but I'll bet the error you're having is this one.
Get-Date : Cannot bind parameter 'Date'. Cannot convert value "+" to type "System.DateTime".
Error: "String was not recognized as a valid DateTime."
This is because the code you've got here is trying to add a character to a PowerShell DateTime object, and that simply does not fly. You can pick a single property though and concatenate characters onto that, however.
But, I noticed that you commented out some lines in your code, and am guessing that you'd like to get the date in this format: "yyyyMMdd-HHmmss".
If that's so, this little snippet will do that for you:
# Define logic to rename and copy .
foreach ($item in $sourceFileList) {
$newFileName = $(Get-Date -UFormat %Y%m%d-%H%m%S) + "_" + $item
"the item $($item.BaseName) would become $newFileName"
}
This will output to the screen the new name for the file, like this:
the item q1 would become 20160921-110907_q1.png
the item q2 would become 20160921-110907_q2.png
the item q3 would become 20160921-110907_q3.png
You can comment out that line once you're happy with the new name. And the best part? Just drop this into your code inplace of your current $newFileName line and it will work with your previous code.
If I'm wrong, let me know the error you're getting and I'll help you get this sorted.
Looks like you are trying to write a file with : in the time part of the Get-Date when you try to rename to $newFileName. This will kick an error out.
$Date = Get-Date.ToString("yyyyMMdd_HHmmss")
$newFileName = $Date + "_" + $item
Include the above and that should prevent that problem.
thanks for everyone's help and input. I really appreciate it. I was finally able to resolve my problem whereby in the variable assigned in the foreach loop the FULL PATH was being defined that is what was generating the errors above. Once I used the .NAME property the issue was resolved. Thanks again to everyone.