Копирование файлов с переименованием, если уже существует PowerShell - PullRequest
0 голосов
/ 30 августа 2018

Этот скрипт работает для переименования файлов при их копировании, если они являются дубликатами. Мне нужно сначала переименовать текущий файл назначения, а затем скопировать исходный файл как есть. Есть идеи?

function Copy-FilesWithVersioning{
    Param(
        [string]$source,
        [string]$destination
    )
    Get-ChildItem -Path $source -File
        ForEach-Object {
            $destinationFile = Join-Path $destination $file.Name
            if ($f = Get-Item $destinationFile -EA 0) {
                # loop for number goes here
                $i = 1
                $newname = $f.Name -replace $f.BaseName, "$($f.BaseName)_$I")
                Rename-Item $destinationFile $newName
            }
            Copy-Item $_ $destination
        }
}

Copy-FilesWithVersioning c:\scripts\Source c:\scripts\DestinationA

Ошибка:

At line:10 char:53
+             if($f = Get-Item $destinationFile -EA 0){
+                                                     ~
Missing closing '}' in statement block or type definition.
At line:8 char:23
+         ForEach-Object{
+                       ~
Missing closing '}' in statement block or type definition.
At line:2 char:34
+ function Copy-FilesWithVersioning{
+                                  ~
Missing closing '}' in statement block or type definition.
At line:13 char:77
+ ...         $newname = $f.Name -replace $f.BaseName, "$($f.BaseName)_$I")
+                                                                         ~
Unexpected token ')' in expression or statement.
At line:15 char:13
+             }
+             ~
Unexpected token '}' in expression or statement.
At line:17 char:9
+         }
+         ~
Unexpected token '}' in expression or statement.
At line:18 char:1
+ }
+ ~
Unexpected token '}' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingEndCurlyBrace

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

Попробуйте код по этой ссылке: https://www.pdq.com/blog/copy-individual-files-and-rename-duplicates/:

$SourceFile = "C:\Temp\File.txt"
$DestinationFile = "C:\Temp\NonexistentDirectory\File.txt"

If (Test-Path $DestinationFile) {
    $i = 0
    While (Test-Path $DestinationFile) {
        $i += 1
        $DestinationFile = "C:\Temp\NonexistentDirectory\File$i.txt"
    }
} Else {
    New-Item -ItemType File -Path $DestinationFile -Force
}

Copy-Item -Path $SourceFile -Destination $DestinationFile -Force 
0 голосов
/ 30 августа 2018

Ошибки, которые вы видите, вызваны ложными закрывающими скобками в этой строке:

$newname = $f.Name -replace $f.BaseName, "$($f.BaseName)_$I")

Удалите скобки в конце строки, и эти ошибки исчезнут.

Однако в вашем коде есть несколько других ошибок, поэтому даже после исправления код все равно не будет работать.

  • Вам не хватает трубы между Get-ChildItem и ForEach-Object. Требуется для передачи вывода одного командлета другому.

    Get-ChildItem -Path $source -File |
        ForEach-Object {
            ...
        }
    
  • Переменная $file не определена. В конвейере PowerShell вы хотите работать с переменной «текущий объект» ($_). Изменить эту строку

    $destinationFile = Join-Path $destination $file.Name
    

    в

    $destinationFile = Join-Path $destination $_.Name
    
  • $_ в выписке

    Copy-Item $_ $destination
    

    расширяется только до имени файла, а не полного пути. Измените это на

    Copy-Item $_.FullName $destination
    

    Еще лучше, переместите оператор Copy-Item после ForEach-Object, чтобы вам не нужно было явно указывать источник в первую очередь (командлет читает входные данные из конвейера):

    Get-ChildItem ... | ForEach-Object {
        ...
        $_   # need this line to pass the current object back into the pipeline
    } | Copy-Item -Destination $destination
    

    Обратите внимание, что необходимо вывести текущий объект обратно в конвейер и указать пункт назначения в качестве именованного параметра (-Destination $destination), чтобы последний работал.

  • Проверка наличия файла в папке назначения немного неловкая. Вместо этого используйте Test-Path. Вы можете создать новое имя файла из текущего объекта.

    if (Test-Path -LiteralPath $destinationFile) {
        $i = 1
        Rename-Item $destinationFile ($_.BaseName + "_$i" + $_.Extension)
    }
    
...