我有一个如下所示的目录结构:
c:\folderA\folderB\folderC\client1\f1\files
c:\folderA\folderB\folderC\client1\f2\files
c:\folderA\folderB\folderC\client2\f1\files
c:\folderA\folderB\folderC\client2\f2\files
c:\folderA\folderB\folderC\client3\f1\files
c:\folderA\folderB\folderC\client4\f2\files
我想复制c:\ tmp \中f1文件夹的内容来获取此
c:\tmp\client1\f1\files
c:\tmp\client2\f1\files
c:\tmp\client3\f1\files
我试过了:
copy-item -recur -path: "*/f1/" -destination: c:\tmp\
但是它复制了内容而没有正确复制结构。
答案 0 :(得分:42)
在PowerShell 3.0及更高版本中,这只是通过这种方式完成的:
Get-ChildItem -Path $sourceDir | Copy-Item -Destination $targetDir -Recurse -Container
答案 1 :(得分:12)
使用xcopy
或robocopy
,这两者都是为此目的而设计的。假设您的路径当然只是文件系统路径。
答案 2 :(得分:11)
<强> Powershell的:强>
$sourceDir = 'c:\folderA\folderB\folderC\client1\f1'
$targetDir = ' c:\tmp\'
Get-ChildItem $sourceDir -filter "*" -recurse | `
foreach{
$targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length);
New-Item -ItemType File -Path $targetFile -Force;
Copy-Item $_.FullName -destination $targetFile
}
注意:
答案 3 :(得分:7)
这里有另一个答案,同样的解决方案虽然不是很清楚所以我会把它扔进去,因为我花了一段时间才找到这个答案。
我一直在挖掘并找到了很多解决这个问题的方法,所有这些都是一些改动而不仅仅是一个直接的copy-item命令。在PS 3.0之前给出一些这些问题,所以答案没有错,但是使用powershell 3.0我终于能够使用-Container开关来实现这一点。
Copy-Item $from $to -Recurse -Container
这是我运行的测试,没有错误,目标文件夹代表相同的文件夹结构。
New-Item -ItemType dir -Name test_copy
New-Item -ItemType dir -Name test_copy\folder1
New-Item -ItemType file -Name test_copy\folder1\test.txt
#NOTE: with no \ at the end of the destination the file is created in the root of the destination, does not create the folder1 container
#Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2 -Recurse -Container
#if the destination does not exists this created the matching folder structure and file with no errors
Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2\ -Recurse -Container
希望这有助于某人
答案 4 :(得分:4)
如果要使用PowerShell正确复制文件夹结构,请执行以下操作:
$sourceDir = 'C:\source_directory'
$targetDir = 'C:\target_directory'
Get-ChildItem $sourceDir -Recurse | % {
$dest = $targetDir + $_.FullName.SubString($sourceDir.Length)
If (!($dest.Contains('.')) -and !(Test-Path $dest))
{
mkdir $dest
}
Copy-Item $_.FullName -Destination $dest -Force
}
这说明了创建目录并只复制文件。当然,如果您的文件夹包含句点,则需要修改上面的Contains()调用;如果您想要搜索“f1”,则需要添加过滤器。
答案 5 :(得分:3)
Container开关维护文件夹结构。享受。
testing>> tree
Folder PATH listing
Volume serial number is 12D3-1A3F
C:.
├───client1
│ ├───f1
│ │ └───files
│ └───f2
│ └───files
├───client2
│ ├───f1
│ │ └───files
│ └───f2
│ └───files
├───client3
│ └───f1
│ └───files
└───client4
└───f2
└───files
testing>> ls client* | % {$subdir=(join-path $_.fullname f1); $dest=(join-path temp ($_
.name +"\f1"));if(test-path ($subdir)){ copy-item $subdir $dest -recurse -container -fo
rce}}
testing>> tree
Folder PATH listing
Volume serial number is 12D3-1A3F
C:.
├───client1
│ ├───f1
│ │ └───files
│ └───f2
│ └───files
├───client2
│ ├───f1
│ │ └───files
│ └───f2
│ └───files
├───client3
│ └───f1
│ └───files
├───client4
│ └───f2
│ └───files
└───temp
├───client1
│ └───f1
│ └───files
├───client2
│ └───f1
│ └───files
└───client3
└───f1
└───files
testing>>
答案 6 :(得分:2)
我需要做同样的事情,所以我找到了这个命令:
XCopy souce_path destination_path /E /C /I /F /R /Y
在你的情况下:
XCopy c:\folderA\folderB\folderC c:\tmp /E /C /I /F /R /Y
如果您需要排除某些项目,请创建包含排除列表的文本文件。 E.g:
在驱动器C:\上创建文本文件'exclude.txt'并在其中添加:
.svn
.git
你的复制命令现在看起来像这样:
XCopy c:\folderA\folderB\folderC c:\tmp /EXCLUDE:c:\exclude.txt /E /C /I /F /R /Y
答案 7 :(得分:1)
以下为我工作
@echo off
setlocal enableextensions disabledelayedexpansion
set "target=e:\backup"
for /f "usebackq delims=" %%a in ("TextFile.txt") do (
md "%target%%%~pa" 2>nul
copy /y "%%a" "%target%%%~pa"
)
对于列表中的每一行(文件),在目标文件夹下创建readed行中指示的相同路径(%%〜pa是%% a引用的元素的路径)。然后,将readed文件复制到目标文件夹
答案 8 :(得分:1)
自从我花时间寻找一种更简单的方法,该方法不涉及管道或内联脚本:
Copy-Item -Path $sourceDir -Destination $destinationDir -Recurse -Container -Verbose
如果需要复制条件,则还可以提供-Filter
参数。
使用PowerShell 5.1.18362.752。
答案 9 :(得分:0)
$sourceDir = 'C:\source_directory'
$targetDir = 'C:\target_directory'
Get-ChildItem $sourceDir -Recurse | % {
$dest = $targetDir + $_.FullName.SubString($sourceDir.Length)
If (!($dest.Contains('.')) -and !(Test-Path $dest))
{
mkdir $dest
}
Copy-Item $_.FullName -Destination $dest -Force
}
此代码有效,尤其是当您将Get-ChildItem与filter / where-object方法结合使用时。
但是,此代码存在一个小错误: 通过“ IF”语句和以下代码“ mkdir”,将在$ targetDir上创建文件夹...之后,命令“ copy-item”在由“ mkdir”命令创建的文件夹内创建相同的文件夹。>
这里是“ Where-Object”功能如何为我工作的示例。 您可以简单地省略IF语句。
$Sourcefolder= "C:\temp1"
$Targetfolder= "C:\temp2"
$query = Get-ChildItem $Sourcefolder -Recurse | Where-Object {$_.LastWriteTime -gt [datetime]::Now.AddDays(-1)}
$query | % {
$dest = $Targetfolder + $_.FullName.SubString($Sourcefolder.Length)
Copy-Item $_.FullName -Destination $dest -Force
}
确保路径的末尾不带“ \”。
答案 10 :(得分:0)
我有一个相似的要求,即我只想共享库文件(不同的平台和构建类型)。我正准备编写PowerShell脚本,我意识到可以使用“ SyncBackFree”工具在不到一分钟的时间内完成该脚本。它按预期工作。
1>创建个人资料
2>选择源和目标文件夹
3>单击“选择子目录和文件
4>单击左侧的“更改过滤器”
5>添加文件扩展名(“ * .lib”)和“ * \”(用于文件夹结构)
答案 11 :(得分:0)
忘记复制项,它永远不会做您期望的事情,Invoke-Expression调用命令行命令并允许使用powershell变量。我在/ E上使用了较旧的xcopy命令,因此目录被复制(也为空目录)和/ Y来抑制提示并确认覆盖。
$sourceDir = "c:\source\*"
$targetDir = "c:\destination\"
Invoke-Expression "xcopy $sourceDir $targetDir /E /Y"
答案 12 :(得分:0)
通常,只要目标文件夹已经存在,Copy-Item 就会为您执行此操作。 documentation 与我通过测试验证的内容不符。目标路径中的尾部斜杠无法解决此问题。复制文件夹层次结构时,必须使用 -Recurse。 Container 参数默认为 true,您可以将其关闭。
在您的问题中,您正在根据命名的子文件夹过滤要复制的文件列表。虽然这适用于 Copy-Item 的 Path 属性,但问题是目标文件夹 ( client* ) 不存在,这就是文件被放置在目标文件夹的根目录中的原因。大多数其他答案没有专门针对这种情况,因此没有回答所提出的问题。要实现您的解决方案,这将需要两个步骤:
$source = 'C:\FolderA\FolderB\FolderC'
$dest = 'C:\tmp'
# Only need the full name
$files = Get-ChildItem -Path $source -Recurse -File | Where-Object { $_.FullName -match '^.+\\client\d\\f1\\.+\..+$' } | ForEach-Object { $_.FullName }
# Iterate through the list copying files
foreach( $file in $files ) {
$destFile = $file.Replace( $source, $dest )
$destFolder = Split-Path -Path $destFile -Parent
# Make sure the destination folder for the file exists
if ( -not ( Test-Path -Path $destFolder ) ) {
New-Item -Path ( Split-Path -Path $destFolder -Parent ) -Name ( Split-Path -Path $destFolder -Leaf ) -ItemType Directory -Force
}
Copy-Item -Path $file -Destination $destFolder
}
答案 13 :(得分:0)
$source ="c:\"
$destination="c:\tmp"
sl $source
md $destination
ls "." -rec -Filter *.zip | %{
$subfolder=($_.FullName)
$pathtrim=($subfolder -split [regex]::escape([system.io.path])::directoryseperatorchar)[-3] # update -2,-3 here to match output, we need 'client1\f1\files' here
echo $pathtrim
$finaldest=Join-Path -Path $destination -ChildPath $pathtrim
cp $source $finaldest -Verbose
}
答案 14 :(得分:0)
我创建了以下函数,该函数将从目录中复制所有文件并保留文件夹结构。然后,您可以指定文件夹结构应开始的起始索引。
function Copy-FileKeepPath {
param (
$filter,$FileToCopy,$des,$startIndex
)
Get-ChildItem -Path $FileToCopy -Filter $filter -Recurse -File | ForEach-Object {
$fileName = $_.FullName
#Remove the first part to ignore from the path.
$newdes=Join-Path -Path $des -ChildPath $fileName.Substring($startIndex)
$folder=Split-Path -Path $newdes -Parent
$err=0
#check if folder exists"
$void=Get-Item $folder -ErrorVariable err -ErrorAction SilentlyContinue
if($err.Count -ne 0){
#create when it doesn't
$void=New-Item -Path $folder -ItemType Directory -Force -Verbose
}
$void=Copy-Item -Path $fileName -destination $newdes -Recurse -Container -Force -Verbose
}
}
如下使用:
Copy-FileKeepPath -FileToCopy 'C:\folderA\folderB\folderC\client1\f1\' -des "C:\tmp" -filter * -startIndex "C:\folderA\folderB\folderC\".Length