Skip to main content
 首页 » 编程设计

powershell之如果不存在,如何将更新的文件复制到新文件夹并创建目录作为源

2025年01月19日1898°冷暖

我试图比较 2 个文件夹中的文件,并将这些新文件和更新后的文件复制到 diff 文件夹中,例如:

newFolder has   
a\aa.txt (new folder and new file)   
b\aa.txt   
b\ab.exe (modified)   
b\ac.config (new file)   
aa.txt (modified)   
ab.exe (new file)   
ac.config 
 
oldFolder has   
b\aa.txt   
b\ab.exe   
aa.txt   
ac.config 

在这种情况下,我期望 diff 文件夹中的内容应该是:

diffFolder     
a\aa.txt   
b\ab.exe   
b\ac.config   
aa.txt   
ab.exe 

到目前为止,我一直在谷歌上搜索并尝试不同的方法,但仍然无法实现。
我得到的文件列表包括需要复制的文件及其路径,方法是使用
xcopy/edyl "newFolder\*""oldFolder"
并尝试使用

for /f %%F in ('xcopy /e /dyl "new\*" "old"') do @xcopy %%F diff /e 

这弄乱了 diffFolder
也试过了

for /f %%F in ('xcopy /e /dyl "new\*" "old"') do @robocopy new diff %%F /e 

这只会在 diffFolder 中创建目录但不会复制文件,给我错误:无效参数 #3 :"newFolder\a\aa.txt"

for /f %%F in ('xcopy /e /dyl "new\*" "old"') do @copy "%%F" "diff" >nul 

只复制文件不创建目录。
我也尝试使用 powershell,但结果与 @copy 相同。

有人可以帮我解决这个具体问题吗?

提前致谢!

请您参考如下方法:

因为这是用 powershell 标签标记的,所以这就是我在 powershell 中的做法。

首先用目录名设置一些变量:

#create path variables 
$olddir = "C:\oldFolder" 
$newdir = "C:\newFolder" 
$diffdir = "C:\diffFolder" 

现在,使用带有 -recurse 参数的 get-childitem 获取每个目录中的文件列表,通过 where-object 进行过滤输出目录:

#Get the list of files in oldFolder 
$oldfiles = Get-ChildItem -Recurse -path $olddir | Where-Object {-not ($_.PSIsContainer)} 
 
#get the list of files in new folder 
$newfiles = Get-ChildItem -Recurse -path $newdir | Where-Object {-not ($_.PSIsContainer)} 

现在,比较列表,但只比较 LastWriteTime 属性(可以使用 Length 代替 LastWriteTime - LastWriteTime ,长度).

确保使用 -Passthru 选项,以便每个文件作为对象传递,所有文件属性仍然可访问。

通过sort-object 管道对LastWriteTime 属性进行排序,因此文件从最旧到最新处理。然后通过管道进入 foreach 循环:

Compare-Object $oldfiles $newfiles -Property LastWriteTime -Passthru | sort LastWriteTime | foreach { 

在循环中,为每个文件构建保留目录结构的新名称(将 olddir 和 newdir 路径替换为 diffdir 路径)。

使用 Split-Path 获取新路径的目录并测试它是否存在 - 如果不存在,使用 mkdir 创建它作为 copy -item 除非复制目录而不是文件,否则不会创建目标目录。

然后,复制文件(您可以在复制命令中使用 -whatif 选项让它只告诉您它将复制什么,而无需实际执行):

     $fl = (($_.Fullname).ToString().Replace("$olddir","$diffdir")).Replace("$newdir","$diffdir") 
     $dir = Split-Path $fl 
     If (!(Test-Path $dir)){ 
        mkdir $dir 
     } 
     copy-item $_.Fullname $fl 
} 

所以完整的脚本是:

#create path variables 
$olddir = "C:\oldFolder" 
$newdir = "C:\newFolder" 
$diffdir = "C:\diffFolder" 
 
#Get the list of files in oldFolder 
$oldfiles = Get-ChildItem -Recurse -path $olddir | Where-Object {-not ($_.PSIsContainer)} 
 
#get the list of files in new folder 
$newfiles = Get-ChildItem -Recurse -path $newdir | Where-Object {-not ($_.PSIsContainer)} 
 
Compare-Object $oldfiles $newfiles -Property LastWriteTime -Passthru | sort LastWriteTime | foreach { 
     $fl = (($_.Fullname).ToString().Replace("$olddir","$diffdir")).Replace("$newdir","$diffdir") 
     $dir = Split-Path $fl 
     If (!(Test-Path $dir)){ 
        mkdir $dir 
     } 
     copy-item $_.Fullname $fl 
}