Commande / script pour copier des fichiers avec certains ext, qui peuvent avoir le même nom, de la structure du dossier au répertoire singe et renommer

À partir d'une structure de répertoire source (plusieurs dossiers), j'ai besoin de copier tous les fichiers csv dans un seul répertoire cible. J'ai trouvé une commande pour le faire, bien que des fichiers du même nom existent dans différents dossiers de la structure source, provoquant des problèmes évidents lorsqu'ils sont copiés dans un seul dossier.

Comment les fichiers avec des noms en double peuvent-ils être renommés pendant la copie s'il vous plaît (idéalement: report.csv, reportcopy2.csv etc.)? Le travail ne copie actuellement qu'une seule instance de chaque fichier. Merci pour l'aide.

C'est un léger travail. Je sais que vous vouliez nommer différemment, mais je me suis demandé si cela fonctionnerait pour vous.

Je vous suggère de renommer sur copie à quelque chose comme Foldername.Filename.csv.

Utilisez quelque chose comme

echo f | xcopy /f /y srcfile destfile 

MODIFIER

J'ai essayé pendant quelques heures, je ne pense pas que ce que vous voulez est possible avec l'invite CMD ou les fichiers bat.

C'est ce que j'ai

 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 

Il échoue sur le renomme parce qu'il ignore la variable. Donc, où je montre newName-% dir% (où dir est la variable), il échouerait sur newName – %% a aussi …

Désolé, je ne pense pas que ce soit possible.

Cela dit, il semble que cela soit possible: Windows-batch-file-to-copy-and-keep-duplicates

Ceci est similaire à celui de la réponse d' Aflat :

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

Cela devrait le faire:

 @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 

Ce qu'il fait:

  • Liste tous les fichiers qui correspondent au motif (le plus à l'intérieur for ) formaté comme nom? Chemin
  • Trier la liste (par nom de fichier)
  • Parses trié liste ligne par ligne (externe for ) et pour chaque ligne (fichier)
    • Si le nom du fichier apparaît la première fois, le copie non modifiée
    • Si le nom du fichier se répète, ajoute le suffixe et count_nr à une copie

Comme il est maintenant, il sera juste écho à la commande de copie au lieu de l'exécuter, afin que vous puissiez l'exécuter en toute sécurité et vérifier sa sortie. Lorsque vous êtes prêt, retirez l' echo de
echo copy "%~2" "%targetPath%\%~n1%sufix%%~x1%"

Une simple fonction PowerShell peut également faire ceci:

 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 

Bien sûr, on pourrait supprimer les commandes "write-host" – ils fournissent simplement des commentaires visuels. En outre, il serait possible de rassembler d'abord les noms de fichier, puis de copier ensuite tous les fichiers dans une boucle distincte, ce qui pourrait accélérer les choses.

  • Faites simplement $ready_for_copying un tableau,
  • Ajoute ( += ) la $inter intervalle de $inter ,
  • Ajoutez la vérification des noms de sortie déjà spécifiés dans les if if (p $inter -in $ready_for_copying Ex. $inter -in $ready_for_copying ),
  • Puis déplacez la commande copy-item à une nouvelle for -block (par exemple for($i = 0; $i -lt $ready_for_copying.Length; $i++)