Comando / script per copiare file con determinata ext, che possono avere lo stesso nome, dalla struttura delle cartelle alla directory singe e rinominare

Dalla struttura della directory di origine (più cartelle), devo copiare tutti i file CSV in una singola directory di destinazione. Ho trovato un command per farlo, anche se i file dello stesso nome esistono in diverse cartelle della struttura di origine, causando problemi evidenti quando sono stati copiati in una cartella.

Come possono essere rinominati i file con nomi duplicati durante la copia (idealmente: report.csv, reportcopy2.csv etc)? Il lavoro attualmente copia solo un'unica istanza di ciascun file. Grazie per l'aiuto.

Questo è un piccolo lavoro intorno – so che hai voluto call in modo diverso, ma mi sono chiesto se questo functionrà per te.

Suggerisco di rinominarti sulla copia a qualcosa come Foldername.Filename.csv.

Utilizza qualcosa di simile

echo f | xcopy /f /y srcfile destfile 

EDIT

Ho provato per alcune ore, non credo che quello che vuoi è ansible con i prompt CMD o i file di pipistrelli.

Questo è quello che ho

 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 

Non riesce a rinominare perché ignora la variabile. Quindi, where sto mostrando newName-% dir% (where dir è la variabile) non sarebbe riuscito a newName – %% a pure …

Mi dispiace, non credo che sia ansible.

Detto questo, ciò sembrerebbe ansible: windows-batch-file-to-copy-and-keep-duplicates

Questo è simile alla risposta di aflat :

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

Questo dovrebbe farlo:

 @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 

Cosa fa:

  • Elenca tutti i file che corrispondono a pattern (più interni for ) formattati come path nome
  • Ordina l'elenco (per nome del file)
  • Pars ha ordinato la row di elenco per row (esterna for ) e per each row (file)
    • se il nome file viene visualizzato per la prima volta, la copia non modificata
    • se il nome del file ripete, aggiunge il suffisso e count_nr a una copia

Come è ora, sarà solo eco il command di copia anziché eseguirlo, quindi è ansible eseguirlo in modo sicuro e verificarlo. Quando sei pronto, basta eliminare l' echo
echo copy "%~2" "%targetPath%\%~n1%sufix%%~x1%"

Una semplice PowerShell-Function può anche farlo:

 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) [arrays]$file_input = @(Get-ChildItem -LiteralPath $path_in -Filter $fileext -Recurse) [arrays]$file_input_path = @($file_input | ForEach-Object {$_.FullName}) [arrays]$file_input_name = @($file_input | ForEach-Object {$_.BaseName}) [arrays]$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 

Naturalmente si potrebbe eliminare i comandi di "scrittura-host" – semplicemente forniscono qualche feedback visivo. Inoltre, sarebbe ansible raccogliere prima i nomi dei file e copiare poi tutti i file in un loop separato, eventualmente accelerando le cose.

  • basta fare $ready_for_copying un arrays,
  • aggiungere ( += ) le $inter valenze ad esso,
  • aggiungere il controllo per i nomi di output già specificati nelle if (ad esempio $inter -in $ready_for_copying ),
  • quindi spostare la copy-item command -command a un nuovo block -b ( for($i = 0; $i -lt $ready_for_copying.Length; $i++) esempio for($i = 0; $i -lt $ready_for_copying.Length; $i++)