How do I overwrite a file using PowerShell? - powershell

New-Item -Path "C:\aws" -Name "script.ps1" -ItemType "file" -Value "text in file"
I am trying to create a file using the above command, if the file already exists I have to replace it with new file, it will have same file name. Please help

Use the force — specifically, the -Force parameter...
New-Item -Path "C:\aws" -Name "script.ps1" -ItemType "file" -Value "text in file" -Force
Whether script.ps1 already exists or not, upon success it will contain the exact content text in file.
Its use is also demonstrated in example #9 of the New-Item documentation...
Example 9: Use the -Force parameter to overwrite existing files
This example creates a file with a value and then recreates the file using -Force. This overwrites The existing file and it will lose it's content as you can see by the length property
PS> New-Item ./TestFile.txt -ItemType File -Value 'This is just a test file'
Directory: C:\Source\Test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 5/1/2020 8:32 AM 24 TestFile.txt
New-Item ./TestFile.txt -ItemType File -Force
Directory: C:\Source\Test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 5/1/2020 8:32 AM 0 TestFile.txt
Omitting -Force from the second invocation of New-Item produces the error New-Item : The file '...\TestFile.txt' already exists..

Related

Powershell Copy-Item -recurse does not pick up new directory

I'm creating a binary PS module with PlatyPS help. I have a local poor-man's deploy script like this (PS 5.1):
$modulepath= "$Env:USERPROFILE\Documents\WindowsPowerShell\Modules"
$releasePath = ".\bin\release\net472"
# build project
dotnet build -c release
# build documentation
# requires PlatyPS module
New-ExternalHelp -Path .\docs -OutputPath $releasePath\en-US -Force
ls $releasePath # debug
# copy files
Get-ChildItem -Path $releasePath | Copy-Item -Destination $modulepath\PoshCommence -Recurse -Force
ls $modulepath\PoshCommence # debug
This ouputs the following surprising result:
Directory: X:\CustomModules\PoshCommence\bin\release\net472
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 17-2-2021 00:31 en-US
-a---- 17-2-2021 00:24 36352 PoshCommence.dll
Directory: C:\Users\XXX\Documents\WindowsPowerShell\Modules\PoshCommence
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 17-2-2021 00:31 871 about_PoshCommence.help.txt <- from en-US folder
-a---- 17-2-2021 00:24 36352 PoshCommence.dll
-a---- 17-2-2021 00:31 141080 PoshCommence.dll-Help.xml <- from en-US folder
None of the directories exist prior to running the script. I deleted the 'bin' project folder as well as the 'PoshCommence' module folder.
It seems either Get-ChildItem or Copy-Item -Recurse do not pick up the newly created 'en-US' directory, but the contents of it do get copied to the root level. If I run the script a second time (without deleting folders), it works as expected (except I still have docs stuff in the root of the module I don't want).
That has me stumped. I have tried -Verbose on everything, I put Start-Sleep after every line thinking operations may need time, but to no avail. Why isn't the 'en-US' folder picked up the first time?
Answering my own question. My confusion stems from the fact that
Copy-Item -Path $source -Destination $destination -Recurse
Works differently depending on whether the folder in $destination already exists or not.
So in the end all it took was
if (!(Test-Path $modulepath\PoshCommence)) { mkdir $modulepath\PoshCommence }
prior to the copying.

Remove-Item -Recurse -Force can't remove symlinks

It seems that Remove-Item -Recurse -Force cannot deal with removing symlinks. How do I recursively delete everything from a given directory with symlinks made all over the place?
MWE:
PS C:\Users\Administrator\Desktop\test> mkdir foo
Directory: C:\Users\Administrator\Desktop\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 7/30/2020 11:58 AM foo
PS C:\Users\Administrator\Desktop\test> mkdir bar
Directory: C:\Users\Administrator\Desktop\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 7/30/2020 11:58 AM bar
PS C:\Users\Administrator\Desktop\test> New-Item -ItemType SymbolicLink -Path foo -Name bar -Value C:\Users\Administrator\Desktop\test\bar
Directory: C:\Users\Administrator\Desktop\test\foo
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----l 7/30/2020 11:59 AM bar
PS C:\Users\Administrator\Desktop\test> Remove-Item -Recurse -Force foo
Remove-Item : There is a mismatch between the tag specified in the request and the tag present in the reparse point
At line:1 char:1
+ Remove-Item -Recurse -Force foo
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Remove-Item], Win32Exception
+ FullyQualifiedErrorId : System.ComponentModel.Win32Exception,Microsoft.PowerShell.Commands.RemoveItemCommand
The actual CMD equivalent to Remove-Item -Recurse -Force is:
cmd /c rmdir /s /q foo
as it will delete symlinks also in subdirectories. This seems to be good enough for me.
Looks like you are running into the same issue as mentioned here:
https://github.com/powershell/powershell/issues/621
And workaround which is mentioned in this thread is:
Get-ChildItem $somepath -Attributes ReparsePoint | % { $_.Delete() }
Or you can gather more information here:
https://github.com/PowerShell/PowerShell/pull/11331
There's always cmd. Wmi and powershell can't even delete profiles these days because of links.
cmd /c del bar

Powershell - Get-ChildItem wildcard

Get-ChildItem filename*.log.* fetches filename*.log as well. How can I get only the log files ending with dot extension filename*.log.* so I can delete them? I want to use Remove-Item but decided to check using get-childItem.
Here is the files.
Server1234.log
Server1234.log.1
Server1234.log.2
Server1234.log.3
Server1234.log.4
Get-ChildItem filename*.log.* shows all of the above. I don't want Server1234.log in the output.
Your filter should work. I have created 3 files:
New-Item 'Server1234.log' -ItemType File
New-Item 'Server1234.log.1' -ItemType File
New-Item 'Server1234.log.2' -ItemType File
And here is the output of Get-ChildItem Server1234*.log.*
PS D:\> Get-ChildItem Server1234*.log.*
Directory: D:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 13/05/2020 10:51 0 Server1234.log.1
-a---- 13/05/2020 10:51 0 Server1234.log.2
Note: The filter parameter of the Get-ChildItem cmdlet doesn't use regex! If you want to use regex you can do this within the Where-Object cmdlet:
Get-ChildItem | Where-Object { $_.Name -match 'Server123.*log\.+' }
You might use the filter
Get-ChildItem filename*.log.?*
The question mark states that at least one character has to be there...

Renaming my Item with File Name as a Variable not Working using Powershell

I am using Powershell. My goal is to copy one item to a different directory (which I already know how to do), get the userID (which I already know how to do), and rename the file with a file name that exists in a variable (which I am not sure what I am doing wrong).
When I run my code, it gives me an error: Rename-Item : Cannot bind argument to parameter 'NewName' because it is null. I don't know what I am doing wrong.
I got this from https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/rename-item?view=powershell-7
My code is listed below:
$name = [Environment]::UserName
$mainFile = "\\example\example.xlsx"
$copiedFile = "\\example\example\copiedFolder\example.xlsx"
#Once I have copied the file to the new directory, I do the following code which does not work:
$copiedFile = Rename-Item -Path $copiedFile -NewName $name.xlsx
You've way over complicated this. It's a simple copy command.
Get-ChildItem -Path 'D:\temp\reconcile.*'
<#
# Results
Directory: D:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 03-Feb-20 12:54 644 reconcile.txt
#>
$mainFile = 'D:\temp\reconcile.txt'
$FileTarget = 'D:\temp\'
Copy-Item -Path $mainFile -Destination "$FileTarget\reconcile.xlsx" -Force
Get-ChildItem -Path 'D:\temp\reconcile.*'
<#
# Results
Directory: D:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 03-Feb-20 12:54 644 reconcile.txt
-a---- 03-Feb-20 12:54 644 reconcile.xlsx
#>
I am not sure why this...
[Environment]::UserName
...is in your code, and in it twice, since you are not showing how it is being used. However, you can just use the built-in variable for that.
$env:USERNAME
About_EnvironmentVariables
I found the solution, and I feel incredibly dumb for not doing it first. I thank everyone for their input and apologize for all the edits in my previous code. My problem was that I wasn't putting double quotes around $name.xlsx.
This gives me \example\example\copiedFolder\JohnDoe.xlsx Tried single quotes and gave me \example\example\copiedFolder\$name.xlsx instead. Not really sure why. See code below:
$copiedFile = Rename-Item -Path $copiedFile -NewName "$name.xlsx"

Powershell Copy-Item not keeping folder structure

I have the below script to copy data from a local folder to a remote folder created with the current date. However the files are copying but the folder structure is not.
$Date = (Get-Date).ToString("MMddyyyy"),$_.Extension
$Source = "E:\Folder1\\*"
$Dest = "\\Server\Share\Folder2"
$Username = "Username"
$Password = ConvertTo-SecureString "Password" -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential($Username, $Password)
Remove-PSDrive -Name T
Start-Sleep -s 1
New-PSDrive -Name T -PSProvider FileSystem -Root $Dest -Credential $mycreds -Persist
if (!(Test-Path "T:\$Date"))
{
md -Path "T:\$Date"
}
Get-ChildItem -Path $Source -Recurse | % { Copy-Item -Path $_ -Destination "T:\$Date" -Container -Force -Verbose }
Could anyone advise where I am going wrong here?
Thank you.
Nice script, I think we can get this sorted in no time!
Why this happened
The reason this is failing is in this step right here:
Get-ChildItem -Path $Source -Recurse
The -Recurse switch is causing you pain. To illustrate why this is, I created a simple folder structure.
When you run Get-ChildItem -Path $Source -Recurse alone, you'll get a recursive listing of all files in the $Source path, like so:
PS C:\temp\stack> Get-ChildItem -Recurse
Directory: C:\temp\stack
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 8/4/2017 10:50 AM Source
Directory: C:\temp\stack\Source
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 8/4/2017 10:57 AM 1
d----- 8/4/2017 10:57 AM 2
d----- 8/4/2017 10:57 AM 3
d----- 8/4/2017 10:57 AM 4
Directory: C:\temp\stack\Source\1
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 8/4/2017 10:57 AM 20 Archive.rar
-a---- 8/4/2017 10:56 AM 0 File01.bmp
Well, in the next step of your script, you pipe that output over to Copy-Item for every single file.
You're basically expressly telling PowerShell 'take this folder and all of it's subfolders and everything, and dump them all in this one folder, ignoring the folder structure'
How to fix
What you really want to do is simply move the -Recurse parameter over to Copy-Item, and you're done :)
Get-ChildItem -Path $Source |
Copy-Item -Destination "T:\$Date" -Container -Recurse -Force -Verbose
Hope that helps, have a nice 🎃day!
This question is a few years old, but in case someone arrives here like I did...
In another post, a user suggested using robocopy. It worked great for me:
robocopy "source/folder" "target/folder" "*.file_extension" /s
This command copies from the source folder the files that match the given filter, replicating the folder structure in the destination folder.
In this case, it would be used like:
robocopy "E:\Folder1\" "\\Server\Share\Folder2" "*" /s