You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nim脚本调用copyFileWithPermissions报File exists异常求助

问题排查与代码修正

错误原因

你遇到的File exists错误,核心问题是**copyFileWithPermissions的第二个参数需要传入具体的目标文件名,而不是目录路径**。当前你传入的/data/是已经创建好的目录,函数无法直接将文件复制到目录下,必须指定目标文件的完整路径(包括文件名)。

测试代码修正

先把测试代码改对,确保单文件复制正常:

import std/os

# 确保目标目录存在
const targetDir = getCurrentDir() & "/data/"
discard existsOrCreateDir(targetDir)

try:
  # 拼接完整的目标文件名(这里保留原文件名,也可以自定义重命名)
  let srcFile = "source/cr00000.0_00000.csv"
  let targetFile = targetDir & extractFilename(srcFile)
  
  copyFileWithPermissions(
    srcFile, 
    targetFile,
    options = {cfSymlinkIgnore}, 
    ignorePermissionErrors = true
  )
except CatchableError:
  echo getCurrentExceptionMsg()

这里用extractFilename从源路径中提取文件名,自动拼接到目标目录后,避免手动写死文件名。

完整递归遍历+复制重命名实现

针对你需求的“递归遍历目录、复制并重命名”,下面是完整实现示例。假设我们要把所有子目录下的crXXXX.X_XXXXX.csv格式文件,复制到data目录并重命名为file_序号.csv(比如file_1.csv、file_2.csv):

import std/os
import std/strformat

proc processDir(srcDir: string, targetDir: string, var fileCounter: int) =
  # 遍历当前目录下的所有条目
  for entry in walkDir(srcDir):
    case entry.kind:
      # 如果是目录,递归处理
      of pcDir:
        processDir(entry.path, targetDir, fileCounter)
      # 如果是文件,且符合目标格式
      of pcFile:
        let filename = extractFilename(entry.path)
        if filename.startsWith("cr") and filename.endsWith(".csv"):
          # 自定义重命名规则:file_1.csv、file_2.csv...
          let newFilename = fmt"file_{fileCounter}.csv"
          let targetFile = targetDir & newFilename
          
          try:
            copyFileWithPermissions(
              entry.path, 
              targetFile,
              options = {cfSymlinkIgnore}, 
              ignorePermissionErrors = true
            )
            echo fmt"复制成功:{entry.path} → {targetFile}"
            fileCounter.inc()
          except CatchableError:
            echo fmt"复制失败 {entry.path}:{getCurrentExceptionMsg()}"
      else:
        discard # 忽略其他类型的条目

when isMainModule:
  const srcRootDir = "source" # 要遍历的源根目录
  const targetDir = getCurrentDir() & "/data/"
  
  discard existsOrCreateDir(targetDir)
  var counter = 1
  processDir(srcRootDir, targetDir, counter)
  echo fmt"处理完成,共复制 {counter-1} 个文件"

关键细节说明

  • walkDir:递归遍历目录的核心函数,会返回目录下的所有文件和子目录条目
  • extractFilename:从完整路径中提取文件名,避免路径拼接错误
  • 重命名规则可以根据你的需求修改,比如保留原文件的部分前缀、结合原目录名等,只要调整newFilename的生成逻辑即可
  • 异常处理:每个文件复制单独加try-catch,避免一个文件复制失败导致整个脚本中断

内容的提问来源于stack exchange,提问作者Thomas Petit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 01:20:03