Comando / script para copiar arquivos com determinado ext, que pode ter o mesmo nome, da estrutura de pastas para o diretório singe e renomear

2

De uma estrutura de diretório de origem (várias pastas), preciso copiar todos os arquivos csv para um único diretório de destino. Eu encontrei um comando para fazer isso, embora existam arquivos com o mesmo nome dentro de pastas diferentes da estrutura de origem, causando problemas óbvios quando copiados para uma pasta.

Como os arquivos com nomes duplicados podem ser renomeados durante a cópia (idealmente: report.csv, reportcopy2.csv etc)? Atualmente, o trabalho apenas copia uma única instância de cada arquivo. Obrigado por ajuda.

    
por Nick 29.08.2012 / 12:13

4 respostas

0

Esse é um pequeno trabalho - eu sei que você queria dar um nome diferente, mas me perguntei se isso funcionaria para você.

Sugiro que você renomeie a cópia para algo como Foldername.Filename.csv.

Use algo como

echo f | xcopy /f /y srcfile destfile

EDITAR

Eu tentei por algumas horas, eu não acho que o que você quer é possível com o prompt CMD ou arquivos bat.

Isso é o que eu tenho

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

Ele falha na renomeação porque ignora a variável. Então, onde eu estou mostrando newName-% dir% (onde dir é a variável) ele falharia em newName - %% a também ...

Desculpe, não acho que seja possível.

Dito isto, isso faz com que pareça possível: windows-batch-file-para-copy-and-keep-duplicates

    
por 29.08.2012 / 12:34
0

Isso é semelhante a resposta da aflat :

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

Isso deve ser feito:

@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

O que faz:

  • Lista todos os arquivos que correspondem ao padrão (a maioria dos for internos) formatados como nome? caminho
  • Classifica a lista (por nome de arquivo)
  • Analisa lista classificada linha a linha (outer for ) e para cada linha (arquivo)
    • se o nome do arquivo aparecer pela primeira vez, copia-o sem modificações
    • se o nome do arquivo se repetir, adicionar o sufixo e o count_nr a uma cópia

Como é agora, ele irá apenas copiar o comando copy em vez de executá-lo, para que você possa executá-lo com segurança e verificar sua saída. Quando estiver pronto, basta remover echo de echo copy "%~2" "%targetPath%\%~n1%sufix%%~x1%"

    
por 30.08.2012 / 01:53
0

Um simples PowerShell-Function também pode fazer isso:

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

É claro que é possível remover os comandos "write-host" - eles simplesmente fornecem algum feedback visual. Além disso, seria possível primeiro coletar os nomes dos arquivos e depois copiar todos os arquivos em um loop separado, possivelmente acelerando as coisas.

  • basta criar $ready_for_copying uma matriz,
  • adicione ( += ) os $inter -values a ele,
  • adicione a verificação de nomes de saída já especificados no if -conditions (por exemplo, $inter -in $ready_for_copying ),
  • mova o comando copy-item para um novo for -block (por exemplo, for($i = 0; $i -lt $ready_for_copying.Length; $i++)
por 18.06.2017 / 18:43