【问题标题】:Copy file based a specified folder based on file name. Create folder if it doesn't exist根据文件名复制基于指定文件夹的文件。如果文件夹不存在则创建
【发布时间】:2018-11-12 16:48:42
【问题描述】:

我正在尝试根据文件名将文件复制到特定文件夹。

例如:

当前文件夹 - C:\Stuff\Old Files\

文件 - 206.Little Rock.map.pdf

目标文件夹 - D:\Cleanup\206\Repository

所以基本上文件上的前导数字 (206) 是子文件夹的一部分。 “\Repository”将保持不变。只有前导数字会改变。

如果文件是 207.Little Rock.map.pdf,那么目标文件夹是

D:\Cleanup\207\Repository

我从从这里获得的代码开始,但我不确定如何解释数字的变化,以及如果文件夹不存在如何使其创建文件夹。所以 206\Repository 可能已经存在,但如果不存在,我需要脚本来创建文件夹。

$SourceFolder = "C:\Stuff\Old Files\"
$targetFolder = "D:\Cleanup\"
$numFiles = (Get-ChildItem -Path $SourceFolder -Filter *.pdf).Count
$i=0

clear-host;
Write-Host 'This script will copy ' $numFiles ' files from ' $SourceFolder ' to ' $targetFolder
Read-host -prompt 'Press enter to start copying the files'

Get-ChildItem -Path $SourceFolder -Filter *.PDF | %{ 
    [System.IO.FileInfo]$destination = (Join-Path -Path $targetFolder -ChildPath $Name.Repository(".*","\"))

   if(!(Test-Path -Path $destination.Directory )){
    New-item -Path $destination.Directory.FullName -ItemType Directory 
    }
    [int]$percent = $i / $numFiles * 100

    copy-item -Path $_.FullName -Destination $Destination.FullName
    Write-Progress -Activity "Copying ... ($percent %)" -status $_  -PercentComplete $percent -verbose
    $i++
}
Write-Host 'Total number of files read from directory '$SourceFolder ' is ' $numFiles
Write-Host 'Total number of files that was copied to '$targetFolder ' is ' $i
Read-host -prompt "Press enter to complete..."
clear-host;

【问题讨论】:

  • 谢谢!这让我非常接近。我将对其进行更多调整。

标签: powershell directory powershell-2.0 file-copying movefile


【解决方案1】:

您可以尝试以下方法。目录的编号是从正则表达式匹配中获取的,"(\d+)\..*.pdf"。如果您确信将制作正确的文件副本,请从 Copy-Item cmdlet 中删除 -WhatIf

我没有尝试解决Write-Progress 功能。此外,这只会复制以数字开头后跟一个句号(句点)字符的 .pdf 文件。

我不完全理解所有Write-HostRead-Host 用法的必要性。它不是很 PowerShell。呸呸呸

$SourceFolder = 'C:/src/t/copymaps'
$targetFolder = 'C:/src/t/copymaps/base'

$i = 0
$numFiles = (
    Get-ChildItem -File -Path $SourceFolder -Filter "*.pdf" |
        Where-Object -FilterScript { $_.Name -match "(\d+)\..*.pdf" } |
        Measure-Object).Count

clear-host;
Write-Host 'This script will copy ' $numFiles ' files from ' $SourceFolder ' to ' $targetFolder
Read-host -prompt 'Press enter to start copying the files'

Get-ChildItem -File -Path $SourceFolder -Filter "*.pdf" |
    Where-Object -FilterScript { $_.Name -match "(\d+)\..*.pdf" } |
    ForEach-Object {
        $NumberDir = Join-Path -Path $targetFolder -ChildPath $Matches[1]
        $NumberDir = Join-Path -Path $NumberDir -ChildPath 'Repository'
        if (-not (Test-Path $NumberDir)) {
            New-Item -ItemType Directory -Path $NumberDir
        }

        Copy-Item -Path $_.FullName -Destination $NumberDir -Whatif
        $i++
    }

Write-Host 'Total number of files read from directory '$SourceFolder ' is ' $numFiles
Write-Host 'Total number of files that was copied to '$targetFolder ' is ' $i
Read-host -prompt "Press enter to complete..."
clear-host;

【讨论】:

    【解决方案2】:

    这应该大部分满足你的需要。您可能需要稍微调整目标路径,但这应该很容易弄清楚。我强烈建议使用“-”作为文件前缀的分隔符,而不是“。”因为如果您碰巧在错误的位置执行它,这将防止意外移动目录中的每个文件。

    此外,当您编写脚本时,请务必创建函数来完成各个工作单元,然后在最后调用这些函数。以这种方式修改和调试要容易得多。

    <#
    .SYNOPSIS
      Moves files from source to destination based on FileName
      Creates destination folder if it does not exist. 
    .DESCIPTION
      The script expects files with a prefix defined by a hyphen '-' i.e. 200-<filename>.<ext>.
      There is no filename validation in this script; it will *probably* skip files without a prefix.
      A folder based on the prefix will be created in the destination. 
      If your file is name string-cheese.txt then it will be moved to $DestinationIn\string\string-cheese.txt
    .PARAMETER SourceIn
      Source Path (folder) where your files exist.
    .PARAMETER DestinationIn
      Target Path (folder) where you want your files to go.
    .EXAMPLE
      & .\CleanUp-Files.ps1 -SourceIn "C:\Users\User\Documents\Files\" -DestinationIn "C:\Users\User\Documents\Backup\" -Verbose
    .NOTES
      Author: RepeatDaily
      Email: RepeatedDaily@gmail.com
    
      This script is provided as is, and will probably work as intended.  Good Luck!
      https://*.com/questions/50662140/copy-file-based-a-specified-folder-based-on-file-name-create-folder-if-it-doesn
    #>
    [CmdletBinding()]
    param (
      [string]$SourceIn,
      [string]$DestinationIn
    )
    
    function Set-DestinationPath {
      param (
        [string]$FileName,
        [string]$Target
      )
      [string]$NewParentFolderName = $FileName.SubString(0,$FileName.IndexOf('-'))
      [string]$DestinationPath = Join-Path -Path $Target -ChildPath $NewParentFolderName
    
      return $DestinationPath
    }  
    
    function Create-DestinationPath {
      [CmdletBinding()]
      param (
        [string]$Target
      )
      if (-not(Test-Path -Path $Target)) {
        Try {
          New-Item -ItemType Directory -Path $Target | Write-Verbose
        }
        catch {
          Write-Error $Error[0];
        }
      }
      else {
        Write-Verbose "$Target exists"
      }
    }
    
    function Move-MyFiles {
      [CmdletBinding()]
      param (
        [string]$Source,
        [string]$Destination
      )
      [array]$FileList = Get-ChildItem $Source -File | Select-Object -ExpandProperty 'Name'
    
      foreach ($file in $FileList) {
        [string]$DestinationPath = Set-DestinationPath -FileName $file -Target $Destination
    
        Create-DestinationPath -Target $DestinationPath
    
        try {
          Move-Item -Path (Join-Path -Path $Source -ChildPath $file) -Destination $DestinationPath | Write-Verbose
        }
        catch {
          Write-Warning $Error[0]
        }
      }
    }
    
    Move-MyFiles -Source $SourceIn -Destination $DestinationIn
    

    【讨论】:

      最近更新 更多