命令/脚本将具有特定扩展名(可能具有相同名称)的文件从文件夹结构复制到单个目录并重命名

命令/脚本将具有特定扩展名(可能具有相同名称)的文件从文件夹结构复制到单个目录并重命名

我需要从源目录结构(多个文件夹)将所有 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++)

相关内容