2

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

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

4 ответа4

0

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

Я бы посоветовал вам переименовать на копии что-то вроде 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

0

Это должно сделать это:

@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), отформатированному как имя?дорожка
  • Сортирует список (по имени файла)
  • Анализирует отсортированный список построчно (внешний for) и для каждой строки (файла)
    • если имя файла появляется впервые, копирует его без изменений
    • если имя файла повторяется, добавляет суффикс и count_nr к копии

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

0

Простая 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 -com в новый for -block (например, for($i = 0; $i -lt $ready_for_copying.Length; $i++)
0

Это похоже на ответ афлат:

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .