Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell Remove-Item IF file already exists after Copy-item

Tags:

powershell

I need to add a safety net in my script. I'm trying to do a copy job based on a list of users provided through a txt file. Copy the files from that users home directory to a new location. Once the files are copied, check if the file exists in the new location. If yes, then Remove-Item.

Can someone help me? I just don't know how to implement the "if file exists" logic.

$username = Get-Content '.\users.txt'
foreach ($un in $username)
{
  $dest = "\\server\homedirs\$un\redirectedfolders"
  $source = "\\server\homedirs\$un"
  New-Item -ItemType Directory -Path $dest\documents, $dest\desktop

  Get-ChildItem $source\documents -Recurse -Exclude '*.msg' | Copy-Item -Destination $dest\documents
  Get-ChildItem $source\desktop -Recurse -Exclude '*.msg' | Copy-Item -Destination $dest\desktop

  Get-ChildItem $source\mydocuments, $source\desktop -Recurse -Exclude '*.msg' | Remove-Item -Recurse
}
like image 412
Refried04 Avatar asked Apr 21 '14 23:04

Refried04


People also ask

What is copy item PowerShell?

The Copy-Item cmdlet copies an item from one location to another location in the same namespace. For instance, it can copy a file to a folder, but it can't copy a file to a certificate drive. This cmdlet doesn't cut or delete the items being copied.

Does PowerShell copy item overwrite existing files?

By default, when you will copy item in PowerShell using the Copy-Item, it will overwrite the files in the destination folder. The above PowerShell script will overwrite the files but it will show an error for folders: Copy-Item : An item with the specified name D:\Bijay\Destination\Folder1 already exists.

How do you delete a file if it exists in PowerShell?

Subscribe to ShellGeek! PowerShell Test-Path cmdlet check if file exists or not. If file exists, it will return $True and $False if the file doesn't exist on a specified path. PowerShell Remove-Item cmdlet is used to delete the file if exists from the specified path by the $FileName variable.


2 Answers

The shortest way to delete file if it doesn't exist is NOT to use Test-Path but:

rm my_file.zip -ea ig

This is short version of

rm my_file.zip -ErrorAction Ignore

which is much more readable and more DRY then

if (Test-Path my_file.zip) { rm my_file.zip }

like image 197
majkinetor Avatar answered Oct 17 '22 05:10

majkinetor


To answer your question per se, you can do it like this:

Get-ChildItem $source\mydocuments, $source\desktop -Recurse -Exclude '*.msg' | %{
  if (Test-Path ($_. -replace "^$([regex]::escape($source))","$dest")) {
    Remove-Item $_ -Recurse
  }
}
  • Test-Path returns $true if the file at the given path exists, otherwise $false.
  • $_ -replace "^$([regex]::escape($source))","$dest" converts the path of each source item you're enumerating with the corresponding destination path, by replacing $source at the beginning of the path with $dest.
  • The basic regex for the first argument to the -replace operator is ^$source (which means "match the value of $source at the beginning of the string"). However, you need to use [regex]::escape in case $source contains any regex special characters, which is in fact extremely likely with Windows paths, since they contain backslashes. For example, the value you've given here for $source contains \s, which in a regex means "any whitespace character". $([regex]::escape($source)) will interpolate the value of $source with any regex special characters properly escaped, so that you're matching the explicit value.

That said, if your purpose is to copy each item to a new location, and remove the original only if the copy to the new location is successful, it seems like you're reinventing the wheel. Why not just use Move-Item instead of Copy-Item?


Not directly related to the question, but rather than repeating the same command for each subdirectory, you can use a foreach loop:

foreach ($subdir in (echo documents desktop)) {
  # Whatever command you end up using to copy or move the items, 
  # using "$source\$subdir" and "$dest\$subdir" as the paths
}
like image 44
Adi Inbar Avatar answered Oct 17 '22 04:10

Adi Inbar