Копировать файл на основе указанной папки на основе имени файла. Создать папку, если она не существует

Я пытаюсь скопировать файлы в определенную папку на основе имени файла.

Например:

Текущая папка - C:\Stuff\Old Files\

Файл- 206.Little Rock.map.pdf

Папка назначения — D:\Cleanup\206\Repository

Таким образом, в основном начальный номер файла (206) является частью подпапки. «\Repository» останется постоянным. Изменится только начальное число.

Если бы файл был 207.Little Rock.map.pdf, папка назначения была бы

D:\Очистка\207\Репозиторий

Я начал с кода, который я получил отсюда, но я не уверен, как учесть изменение номера и как заставить его создать папку, если папка не существует. Таким образом, 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;

person Wood    schedule 02.06.2018    source источник
comment
Благодарю вас! Это очень близко ко мне. Я собираюсь настроить его еще немного.   -  person Wood    schedule 04.06.2018


Ответы (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: [email protected]

  This script is provided as is, and will probably work as intended.  Good Luck!
  https://stackoverflow.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
person Repeat Daily    schedule 03.06.2018

Вот что вы можете попробовать. Номер каталога берется из совпадения с регулярным выражением, "(\d+)\..*.pdf". Если вы уверены, что будут созданы правильные копии файлов, удалите -WhatIf из командлета Copy-Item.

Я не пытался обращаться к возможности Write-Progress. Кроме того, будут скопированы только файлы .pdf, которые начинаются с цифр, за которыми следует символ ПОЛНОЙ СТОП (точки).

Я не совсем понимаю необходимость использования всех Write-Host и Read-Host. Это не очень PowerShell. pwshic

$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;
person lit    schedule 03.06.2018