复制文件夹结构但根据子目录中的文件夹名称通过两个不同的字符串匹配子文件夹?

Copy folder structure but match subfolders based on the folder name in subdirectories by two different strings?

如何根据两个不同的字符串('Touch' 或 'mpr')复制整个文件夹结构,但只复制 select 某些文件夹下的几个子目录?

我需要的文件在例如:

"C:\Users\Desktop\shizzle\mro\pre\subject_01\Touch"

但是有两个时间点文件夹(Pre 和 Post)和几个主题,因此我尝试了更高的目录:

$includes = 'Touch|mpr'
Get-ChildItem "C:\Users\Desktop\shizzle\mro" -Directory |
    Where-Object{$_.Name -match $includes} |
    Copy-Item -Destination "C:\Users\shizzle\Desktop\shi_data6" -Recurse -Force

效果很好,但前提是搜索到的文件夹在指定目录中,而不是几个子目录下(因此它只在 C:\Users\Desktop\shizzle\mro\pre\subject_01 中有效)。

Get-ChildItem "C:\Users\shizzle\Downloads\copy_test\copy_test\mro" -Recurse | Where-Object{$_.Name -match $includes} | Copy-Item -Destination "C:\Users\shizzle\Downloads\test_shi10" -Recurse -Force

跟不上文件夹结构。

文件夹结构如下所示:

C:\Users\Desktop\shizzle\mro\

+---pre
|   +---subject_01 
|   |   +---dontcopythisfolder
|   |   +---dontcopythisfolder
|   |   +---0024_63_Touch
|   |   |       File_1.txt
|   |   |       File_2.txt
|   |   |       File_3.txt
|   |   +---dontcopythisfolder
|   |   \---654_mpr_8364
|   |          File_1.txt
|   |          File_2.txt
|   |          File_3.txt
|   \---subject_02
|      +---dontcopythisfolder
|      +---dontcopythisfolder
|      +---0024_63_Touch
|      |       File_1.txt
|      |       File_2.txt
|      |       File_3.txt
|      +---dontcopythisfolder
|      \---654_mpr_8364
|             File_1.txt
|             File_2.txt
|             File_3.txt
\---post
   +---subject_01 
   |   +---dontcopythisfolder
   |   +---dontcopythisfolder
   |   +---0024_63_Touch
   |   |       File_1.txt
   |   |       File_2.txt
   |   |       File_3.txt
   |   +---dontcopythisfolder
   |   \---654_mpr_8364
   |          File_1.txt
   |          File_2.txt
   |          File_3.txt
   \---subject_02
      +---dontcopythis folder
      +---dontcopythisfolder
      +---0024_63_Touch
      |       File_1.txt
      |       File_2.txt
      |       File_3.txt
      +---dontcopythisfolder
      \---654_mpr_8364
             File_1.txt
             File_2.txt
             File_3.txt

这就是我所说的字符串操作,试试这个,看看它是否有效:

$basePath="C:\Users\shizzle\Downloads\copy_test\copy_test\mro\"
$includes = 'Touch|mpr'
$destinationPath="C:\Users\shizzle\Downloads\test_shi10"

Get-ChildItem $basePath -Recurse -Directory |
    Where-Object{$_.Name -match $includes} | %{
        $manipulatedPath=Join-Path $destinationPath -ChildPath ($_.FullName -replace $basePath)
        Copy-Item -Path $_.FullName -Destination $manipulatedPath -Recurse -Force
    }

编辑:

为了测试,我在一个测试文件夹中有很多文件夹(忽略它们的名称),并且将在不实际复制文件夹的情况下尝试进行此复制,但要查看它们的“目标路径”是什么。这是代码:

$basePath='/home/zen/Documents/test'
$destinationPath="/home/zen/Desktop/copied_folders"
$i='#'*30

"
$i
My Test Folders:
"
(Get-ChildItem $basePath -Recurse -Directory).FullName

"
$i
My Destination Folders:
"
Get-ChildItem $basePath -Recurse -Directory | %{
        $manipulatedPath=Join-Path $destinationPath -ChildPath ($_.FullName -replace $basePath)
        $manipulatedPath
    }

这是我的 PS 主机向我显示的假定目标路径:

PS /home/zen> /home/zen/Documents/script.ps1

##############################
My Test Folders:

/home/zen/Documents/test/emptycompressedfolder
/home/zen/Documents/test/Folder with Spaces
/home/zen/Documents/test/INC.
/home/zen/Documents/test/RESIDENCES
/home/zen/Documents/test/emptycompressedfolder/emptyfolder
/home/zen/Documents/test/emptycompressedfolder/emptyfolder/emptyfolderinsideemptyfolder
/home/zen/Documents/test/emptycompressedfolder/emptyfolder/emptyfolderinsideemptyfolder/insideemptyfolder
/home/zen/Documents/test/emptycompressedfolder/emptyfolder/emptyfolderinsideemptyfolder/insideemptyfolder/insideeeee

##############################
My Destination Folders:

/home/zen/Desktop/copied_folders/emptycompressedfolder
/home/zen/Desktop/copied_folders/Folder with Spaces
/home/zen/Desktop/copied_folders/INC.
/home/zen/Desktop/copied_folders/RESIDENCES
/home/zen/Desktop/copied_folders/emptycompressedfolder/emptyfolder
/home/zen/Desktop/copied_folders/emptycompressedfolder/emptyfolder/emptyfolderinsideemptyfolder
/home/zen/Desktop/copied_folders/emptycompressedfolder/emptyfolder/emptyfolderinsideemptyfolder/insideemptyfolder
/home/zen/Desktop/copied_folders/emptycompressedfolder/emptyfolder/emptyfolderinsideemptyfolder/insideemptyfolder/insideeeee
PS /home/zen> 

你可以试试这个:

$sourcePath  = 'D:\Test'  # 'C:\Users\Desktop\shizzle\mro'
$Destination = 'D:\Data'  # 'C:\Users\shizzle\Desktop\shi_data6'
$includes    = 'Touch|mpr'
Get-ChildItem -Path $sourcePath -Recurse -Directory |
    Where-Object{$_.Name -match $includes} |
    ForEach-Object {
        $targetPath = Join-Path -Path $Destination -ChildPath $_.Parent.FullName.Substring($sourcePath.Length)
        $null = New-Item -Path $targetPath -ItemType Directory -Force
        $_ | Copy-Item -Destination $targetPath -Recurse -Force
    }

除了使用上面的Substring()方法,还可以使用正则表达式-replace构造目标路径
但是,请记住,路径包含对正则表达式具有特殊含义的字符,因此您应该使用源路径的 [regex]::Escape() 版本,并使用 [=17= 将其锚定到字符串的开头]:

$sourcePath  = 'D:\Test'  # 'C:\Users\Desktop\shizzle\mro'
$Destination = 'D:\Data'  # 'C:\Users\shizzle\Desktop\shi_data6'
$includes    = 'Touch|mpr'

# if you want to use regex `-replace` instead, use this:
$escapedSource = '^{0}' -f [regex]::Escape($sourcePath)
Get-ChildItem -Path $sourcePath -Recurse -Directory |
    Where-Object{$_.Name -match $includes} |
    ForEach-Object {
        $targetPath = Join-Path -Path $Destination -ChildPath ($_.FullName -replace $escapedSource)
        $null = New-Item -Path $targetPath -ItemType Directory -Force
        $_ | Copy-Item -Destination $targetPath -Recurse -Force
    }

下面是我测试的结果(当然使用不同的路径..)

来源

D:\TEST
+---post
|   +---subject_01
|   |   +---0024_63_Touch
|   |   |       File1.txt
|   |   |       File2.txt
|   |   |
|   |   +---654_mpr_8364
|   |   |       File1.txt
|   |   |       File2.txt
|   |   |
|   |   +---dontcopythisfolder
|   |   \---ignorethisonetoo
|   \---subject_02
|       +---0024_63_Touch
|       |       File1.txt
|       |       File2.txt
|       |
|       +---654_mpr_8364
|       |       File1.txt
|       |       File2.txt
|       |
|       +---dontcopythisfolder
|       \---ignorethisonetoo
\---pre
    +---subject_01
    |   +---0024_63_Touch
    |   |       File1.txt
    |   |       File2.txt
    |   |
    |   +---654_mpr_8364
    |   |       File1.txt
    |   |       File2.txt
    |   |
    |   +---dontcopythisfolder
    |   \---ignorethisonetoo
    \---subject_02
        +---0024_63_Touch
        |       File1.txt
        |       File2.txt
        |
        +---654_mpr_8364
        |       File1.txt
        |       File2.txt
        |
        +---dontcopythisfolder
        \---ignorethisonetoo

目的地

D:\DATA
+---post
|   +---subject_01
|   |   +---0024_63_Touch
|   |   |       File1.txt
|   |   |       File2.txt
|   |   |
|   |   \---654_mpr_8364
|   |           File1.txt
|   |           File2.txt
|   |
|   \---subject_02
|       +---0024_63_Touch
|       |       File1.txt
|       |       File2.txt
|       |
|       \---654_mpr_8364
|               File1.txt
|               File2.txt
|
\---pre
    +---subject_01
    |   +---0024_63_Touch
    |   |       File1.txt
    |   |       File2.txt
    |   |
    |   \---654_mpr_8364
    |           File1.txt
    |           File2.txt
    |
    \---subject_02
        +---0024_63_Touch
        |       File1.txt
        |       File2.txt
        |
        \---654_mpr_8364
                File1.txt
                File2.txt