【问题标题】:Copy folder structure but match subfolders based on the folder name in subdirectories by two different strings?复制文件夹结构但根据子目录中的文件夹名称通过两个不同的字符串匹配子文件夹?
【发布时间】:2021-03-21 16:23:38
【问题描述】:

如何通过两个不同的字符串(“Touch”或“mpr”)根据文件夹名称复制整个文件夹结构,但只选择几个子目录下的一些文件夹?

我需要的文件在例如:

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

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

$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

【问题讨论】:

  • 您需要对 -Destination 参数进行字符串操作。 -Destination $manipulatedPath 而不是 -Destination "C:\Users\shizzle\Downloads\test_shi10"
  • 谢谢,我试过$manipulatedPath = "C:\Users\shizzle\Downloads\test_shi16"Get-ChildItem "C:\Users\shizzle\Downloads\copy_test\copy_test\mro" -Recurse | Where-Object{$_.Name -match $includes} | Copy-Item -Destination $manipulatedpath -Recurse -Force 但不幸的是没有骰子

标签: powershell recursion match get-childitem copy-item


【解决方案1】:

你可以试试这个:

$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()'d 版本的源路径,并使用 ^ 将其锚定到字符串的开头:

$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

【讨论】:

  • 太棒了,这就像一个魅力!
【解决方案2】:

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

$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> 

【讨论】:

  • 不幸的是,我无法让它工作。 get-Childitem 命令给了我这个错误The regular expression pattern C:\Users\shizzle\Downloads\copy_test\copy_test\mro is not valid. At line:3 char:9 + $manipulatedPath=Join-Path $destinationPath -ChildPath ($_.Fu ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (C:\Users\shizzl...t\copy_test\mro:String) [],RuntimeException + FullyQualifiedErrorId : InvalidRegularExpression
  • 不知道为什么它不适合你,但看看我的编辑
  • 再次感谢您的帮助,这很奇怪,但是当我运行您的测试代码时,我仍然遇到相同的错误(它以某种方式认为操纵或基本路径是正则表达式模式(上面的错误消息时执行Get-Childitem))。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-15
  • 2016-09-11
相关资源
最近更新 更多