我需要从源目录结构(多个文件夹)将所有 csv 文件复制到单个目标目录。我找到了一个执行此操作的命令,尽管同名文件存在于源结构的不同文件夹中,复制到一个文件夹时会出现明显的问题。
请问如何在复制过程中重命名重复名称的文件(理想情况下:report.csv、reportcopy2.csv 等)?该作业目前仅复制每个文件的单个实例。谢谢帮助。
答案1
这是一个轻微的解决方法 - 我知道您想用不同的名字,但我想知道这是否适合您。
我建议您将副本重命名为类似 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 批处理文件复制并保留重复项
答案2
这类似于aflat 的回答:
setlocal enableDelayedExpansion
set counter=1
for /r src %%F in (*.csv) do (
copy %%F dest\%%~nF-!counter!%%~xF
set /a counter=counter+1
)
答案3
这应该可以做到:
@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
从
echo copy "%~2" "%targetPath%\%~n1%sufix%%~x1%"
答案4
一个简单的 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
当然,可以删除“写入主机”命令 - 它们只是提供一些视觉反馈。此外,还可以先收集文件名,然后在单独的循环中复制所有文件,这可能会加快速度。
- 只需创建
$ready_for_copying
一个数组, - 将 (
+=
)$inter
值添加到其中, - 在条件中添加对已指定的输出名称的检查
if
(例如$inter -in $ready_for_copying
), - 然后将
copy-item
命令移动到新的for
块(例如for($i = 0; $i -lt $ready_for_copying.Length; $i++)