Команда/скрипт для копирования файлов с определенным расширением, которые могут иметь одинаковые имена, из структуры папок в одну директорию с переименованием.

Вопрос или проблема

Из структуры каталога-источника (несколько папок) мне нужно скопировать все файлы csv в одну целевую директорию. Я нашел команду для этого, но файлы с одинаковыми именами существуют в разных папках структуры источника, что вызывает очевидные проблемы при копировании в одну папку.

Как переименовать файлы с дублирующимися именами во время копирования (идеально: report.csv, reportcopy2.csv и т. д.)? В настоящее время работа копирует только один экземпляр каждого файла. Спасибо за помощь.

Это небольшой обходной путь — я знаю, что вы хотели назвать по-другому, но подумал, подойдет ли это вам.

Я бы предложил переименовать при копировании что-то вроде Foldername.Filename.csv.

Используйте что-то вроде

echo f | xcopy /f /y srcfile destfile

ИЗМЕНИТЬ

Я пытался несколько часов, не думаю, что то, чего вы хотите, возможно с помощью CMD-промпта или bat-файлов.

Вот что у меня есть

set sDir=C:\Documents and Settings\drook\Desktop
set dDir="C:\Documents and Settings\drook\Desktop\Folder\"

cd C:\Documents and Settings\drook\Desktop\
FOR /F %%a in ("*.txt") DO (     
    xcopy "%%a" "C:\Documents and Settings\drook\Desktop\Folder\"
    cd\ 
    cd C:\Documents and Settings\drook\Desktop\Folder\
    ren "%%a" "newName-%dir%.txt"
    cd\
    cd C:\Documents and Settings\drook\Desktop\
)

pause

Не удается переименовать, потому что игнорируется переменная. Поэтому, когда я показываю newName-%dir% (где dir — переменная), он также не сработает на newName-%%a…

Извините, не думаю, что это возможно.

Сказав это, это выглядит так, как будто это возможно: windows-batch-file-to-copy-and-keep-duplicates

Это похоже на ответ aflat:

setlocal enableDelayedExpansion
set counter=1
for /r src %%F in (*.csv) do (
    copy %%F dest\%%~nF-!counter!%%~xF
    set /a counter=counter+1
)

Это должно сработать:

@echo off
setlocal
set "sourcePath=c:\source"
set "targetPath=c:\temp\target"
set "pattern=*.csv"
set prev=""
set count=0

for /f  "tokens=1,2 delims=?" %%F in ('^(for /r "%sourcePath%" %%N in ^("%pattern%"^) do ^@echo %%~nxN?%%N?^)^|sort') do (
  call :copyFile "%%F" "%%G"
  set prev="%%F"
)

goto :eof

:copyFile
  if /I %prev%==%1 (set /a count+=1) else (set count=0)
  if %count%==0 (set sufix=) else (set sufix=Copy%count%)
  echo copy "%~2" "%targetPath%\%~n1%sufix%%~x1%" 
goto :eof

Что это делает:

  • Составляет список всех файлов, соответствующих шаблону (внутренний for) в формате name?path
  • Сортирует список (по имени файла)
  • Анализирует отсортированный список построчно (внешний for) и для каждой строки (файла)
    • если имя файла появляется в первый раз, копирует его без изменений
    • если имя файла повторяется, добавляет суффикс и номер копии

Сейчас он просто выводит команду копирования вместо выполнения, поэтому вы можете безопасно его запустить и проверить вывод. Когда будете готовы, просто удалите echo из
echo copy "%~2" "%targetPath%\%~n1%sufix%%~x1%"

Простая функция PowerShell также может это сделать:

Function Start-FileCopyWDupliCheck(){
    # specify input-path, output-path, renaming-scheme, and file-extension here:
    param(
        [string]$path_in = 'D:\Temp\bla [ ] pfad\[ ]',
        [string]$path_out="D:\Temp\mirrbla [123] 123",
        [string]$appendix = "_copy",
        [string]$fileext = "*.*"
    )

    # get all the files (and the necessary attributes)
    [array]$file_input = @(Get-ChildItem -LiteralPath $path_in -Filter $fileext -Recurse)
    [array]$file_input_path = @($file_input | ForEach-Object {$_.FullName})
    [array]$file_input_name = @($file_input | ForEach-Object {$_.BaseName})
    [array]$file_input_ext = @($file_input | ForEach-Object {$_.Extension})

    # check file-names for duplicates:
    for($i = 0; $i -lt $file_input_path.Length; $i++){
        $inter = "$path_out\$($file_input_name[$i])$($file_input_ext[$i])" -replace '[[+]*?()\\.]','\$&'
        if((Test-Path -LiteralPath $inter) -eq $false){
            Write-Host "$inter not found in output-path -> leaving the name the same" -ForegroundColor Green
            $ready_for_copying = $inter
        }else{
            $j = 1
            Write-Host "$inter found in output-path -> appending `"$($appendix)XY`"..." -ForegroundColor Yellow
            while($true){
                $inter = "$path_out\$($file_input_name[$i])$appendix$j$($file_input_ext[$i])" -replace '[[+]*?()\\.]','\$&'
                if((Test-Path -LiteralPath $inter) -eq $true){
                    $j++
                    continue
                }else{
                    Write-Host "$appendix$j is working" -ForegroundColor Green
                    $ready_for_copying = $inter
                    break
                }
            }
        }
        # finally, copy the file:
        Copy-Item -LiteralPath $($file_input_path[$i]) -Destination $ready_for_copying
    }
}

Start-FileCopyWDupliCheck

Конечно, можно удалить команды “write-host”, они просто обеспечивают некоторую визуальную обратную связь.
Также можно было бы сначала собрать имена файлов, а затем позже скопировать все файлы в отдельном цикле, что возможно ускорит процесс.

  • просто сделайте $ready_for_copying массивом,
  • добавляйте (+=) в него значения $inter,
  • добавьте проверку уже указанных имен выходных файлов в if-условия (например, $inter -in $ready_for_copying),
  • затем переместите команду copy-item в новый блок for (например, for($i = 0; $i -lt $ready_for_copying.Length; $i++)

.

Ответ или решение

Чтобы решить задачу по копированию файлов с расширением .csv из сложной структуры каталогов в одну папку с возможностью переименования файлов во избежание конфликта имен, можно использовать несколько подходов. Мы рассмотрим наиболее удобные и распространенные способы, а именно: использование командного файла Windows Batch, а также PowerShell-скрипта.

Решение с помощью Windows Batch

В Windows Batch можно создать скрипт, который будет проходить по всем подкаталогам, копировать файлы в целевой каталог и при необходимости переименовывать их. Для этого мы используем скрипт, который предоставлен в вопросе, но с небольшой модификацией для выполнения задачи:

@echo off
setlocal enableDelayedExpansion

rem Установка путей источника и назначения
set "sourcePath=C:\source"
set "targetPath=C:\destination"

rem Установка шаблона файла
set "pattern=*.csv"

rem Переменные для учета прошлого имени файла и счетчика
set prevName=""
set count=0

for /r "%sourcePath%" %%F in (%pattern%) do (
    set "fileName=%%~nxF"
    set "fileNameOnly=%%~nF"
    set "fileExtension=%%~xF"

    if /I "!fileName!"=="!prevName!" (
        set /a count+=1
        set "newFileName=!fileNameOnly!_copy!count!!fileExtension!"
    ) else (
        set count=1
        set "newFileName=!fileName!"
    )

    copy "%%F" "%targetPath%\!newFileName!"
    set "prevName=!fileName!"
)

endlocal

Решение с помощью PowerShell

PowerShell предоставляет более развитые возможности для обработки файлов и манипуляции именами файлов. Ниже представлен скрипт, который выполнит аналогичную задачу:

Function Copy-CsvFilesWithRename {
    param(
        [string]$sourcePath = "C:\source",
        [string]$targetPath = "C:\destination",
        [string]$fileExtension = "*.csv"
    )

    if (-Not (Test-Path $targetPath)) {
        New-Item -ItemType Directory -Path $targetPath
    }

    $files = Get-ChildItem -Path $sourcePath -Recurse -Filter $fileExtension
    foreach ($file in $files) {
        $baseName = $file.BaseName
        $extension = $file.Extension
        $destFile = Join-Path $targetPath ($baseName + $extension)

        $i = 1
        while (Test-Path $destFile) {
            $destFile = Join-Path $targetPath ("$baseName" + "_copy$($i)" + $extension)
            $i++
        }

        Copy-Item -Path $file.FullName -Destination $destFile
    }
}

Copy-CsvFilesWithRename

Заключение

Оба предложенные подхода предназначены для автоматизации процесса копирования файлов с их переименованием в случае дублирования имен. Командный файл удобно использовать в среде Windows без дополнительных инструментов, однако PowerShell предлагает более мощный и гибкий инструмент для работы с файлами, что делает его предпочтительным выбором для более сложных задач.

Не забудьте изменить пути к файлам и структурам в предложенных скриптах на соответствующие вашему случаю. Перед выполнением скриптов в производственной среде убедитесь в их корректности и протестируйте их в безопасной тестовой среде.

Оцените материал
Добавить комментарий

Капча загружается...