我有一个非常基本的PowerShell复制脚本,可以将项目从源文件夹复制到目标文件夹。然而,这会移动过多的数据,我想检查文件名是否已经存在,以便可以忽略该文件。我不需要像验证创建的日期/校验和/等那样复杂。
目前它的目的是:
Copy-Item source destination -recurse
Copy-Item source2 destination2 -recurse
我想我需要添加Test-Path cmdlet,但我不确定如何实现它。
答案 0 :(得分:11)
您可以随时从ROBOCOPY
致电PowerShell
。
使用/ xc(不包括已更改)/ xn(不包括更新)和/ xo(不包括旧版)标记:
robocopy /xc /xn /xo source destination
这只会复制那些不在目标文件夹中的文件。
更多选项类型robocopy /?
答案 1 :(得分:4)
虽然我同意Robocopy
是这类事情的最佳工具,但我只是为了给客户提供他们所要求的东西,这是一个有趣的PowerShell练习。
此脚本应该只按照您的要求执行操作:仅当源文件中的文件尚不存在且具有最少的多余装饰时,才将文件从源复制到目标。由于您的示例中有-recurse选项,因此只需在Destination文件夹中测试文件名就可以进行更多编码。
$Source = "C:\SourceFolder"
$Destination = "C:\DestinationFolder"
Get-ChildItem $Source -Recurse | ForEach {
$ModifiedDestination = $($_.FullName).Replace("$Source","$Destination")
If ((Test-Path $ModifiedDestination) -eq $False) {
Copy-Item $_.FullName $ModifiedDestination
}
}
答案 2 :(得分:3)
$exclude = Get-ChildItem -recurse $dest
Copy-Item -Recurse $file $dest -Verbose -Exclude $exclude
答案 3 :(得分:2)
这是一个递归脚本,它同步处理2个文件夹而忽略现有文件:
function Copy-FilesAndFolders([string]$folderFrom, [string]$folderTo) {
$itensFrom = Get-ChildItem $folderFrom
foreach ($i in $itensFrom)
{
if ($i.PSIsContainer)
{
$subFolderFrom = $folderFrom + "\" + $i.BaseName
$subFolderTo = $folderTo + "\" + $i.BaseName
Copy-FilesAndFolders $subFolderFrom $subFolderTo | Out-Null
}
else
{
$from = $folderFrom + "\" + $i.Name
$to = $folderTo + "\" + $i.Name
if (!(Test-Path $from)) # only copies non-existing files
{
if (!(Test-Path $fodlerTo)) # if folder doesn't exist, creates it
{
New-Item -ItemType "directory" -Path $folderTo
}
Copy-Item $from $folderTo
}
}
}
}
要调用它:
Copy-FilesAndFolders "C:\FromFolder" "C:\ToFolder"
答案 4 :(得分:1)
建立Wai Ha Lee的帖子,这是一个对我有用的例子:
> microbenchmark(f.old(),f.new())
Unit: milliseconds
expr min lq mean median uq max neval
f.old() 49.553825 53.486576 61.701149 57.710147 62.862921 136.02883 100
f.new() 2.036781 2.365426 2.988266 2.685126 3.396083 10.88668 100
这会构建一个要排除的列表,然后将源目录和子目录中的任何pdf复制到单个文件夹中的目标 ...,不包括现有文件。同样,这是我需要的一个例子,但与你的相似。应该很容易调整你的心灵内容。
答案 5 :(得分:1)
函数Copy-IfNotPresent
一次只能接受一个文件,但是很容易为所有要复制的文件循环。这是一个例子:
gci c:\temp\1\*.* -Recurse -File | % { Copy-IfNotPresent -FilePath $_ -Destination "C:\temp\2\$(Resolve-Path $_ -relative)" -Verbose }
这是功能。如有必要,它将生成文件夹树。以下是要点链接:https://gist.github.com/pollusb/cd47b4afeda8edbf8943a8808c880eb8
Function Copy-IfNotPresent {
<#
Copy file only if not present at destination.
This is a one file at a time call. It's not meant to replace complex call like ROBOCOPY.
Destination can be a file or folder. If it's a folder, you can use -Container to force Folder creation when not exists
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory)]
$FilePath,
[Parameter(Mandatory)]
[string]$Destination,
[switch]$Container,
[switch]$WhatIf
)
#region validations
if ($FilePath -isnot [System.IO.FileInfo]){
$File = Get-ChildItem $FilePath -File
} else {
$File = $FilePath
}
if (!$File.Count){
Write-Warning "$FilePath no file found."
return
} elseif ($File.Count -gt 1) {
Write-Warning "$FilePath must resolve to one file only."
return
}
#endregion
# Destination is a folder
if ($Container -or (Test-Path -Path $Destination -PathType Container)) {
if (!(Test-Path $Destination)) {
New-Item -Path $Destination -ItemType Container | Out-Null
}
$Destination += "\$($File.Name)"
}
# Destination is a file
if (!(Test-Path $Destination)) {
if ($WhatIf) {
Write-Host "WhatIf:Copy-IfNotPresent $FilePath -> $Destination"
} else {
# Force creation of parent folder
$Parent = Split-Path $Destination -Parent
if (!(Test-Path $Parent)) {
New-Item $Parent -ItemType Container | Out-Null
}
Copy-Item -Path $FilePath -Destination $Destination
Write-Verbose "Copy-IfNotPresent $FilePath -> $Destination (is absent) copying"
}
} else {
Write-Verbose "Copy-IfNotPresent $Destination (is present) not copying"
}
}
答案 6 :(得分:1)
$source = "c:\source"
$destination = "c:\destination"
$exclude = Get-Childitem -Recurse $destination | ForEach-Object { $_.FullName -replace [Regex]::Escape($destination ), "" }
source
复制到destination
,不包括先前收集的文件。Copy-Item -Recurse -Path (Join-Path $source "*") -Destination $destination -Exclude $exclude -Force -Verbose
(Join-Path $source "*")
最后添加一个通配符,以确保您获得source
文件夹的子代,而不是源文件夹本身。Force
是因为我不介意已经存在文件夹(错误消息的结果)。 谨慎使用。 ForEach-Object { $_.FullName -replace [Regex]::Escape($destination ), "" }
将现有文件的全名转换为可用作Exclude
参数的值