bash 中的 CSV 复制脚本错误报告

bash 中的 CSV 复制脚本错误报告

我有这个脚本,它从主文件夹递归复制 csv 中列出的文件。脚本的复制方面效果很好。但是,我现在想添加一些错误检测功能。我在下面添加的“if”循环无法按我的意愿工作。我已将一个假文件添加到我的 csv 列表中以进行测试,并且脚本报告所有文件均已成功复制,即使其中一个文件不存在。有人可以建议我如何让脚本报告尚未从 csv 成功找到/复制的文件并指定文件名吗?编辑 ** 由于 CSV 中列出了 4000 多个文件,我希望脚本在脚本末尾打印任何复制失败的摘要,而不是针对在此过程中复制的每个文件。这将使识别/总结任何问题变得更加容易。

while IFS=, read -r file rest
do
find $sourcefolder -name "${file}" -exec cp '{}' $destfolder \;
done < $csv
if [ $? -eq 0 ]
then
echo "All files from CSV copied succesfully"
else "File from CSV not copied as not found"
fi

答案1

返回的错误代码find与是否找到任何文件无关。如果命令本身运行失败,它只会返回失败代码。您正在寻找的是这样的:

while IFS=, read -r file rest
do
  find $sourcefolder -name "${file}" -exec cp '{}' $destfolder \;
  ## Check if the file was copied
  [[ -e "$destfolder/$file" ]] || echo "File $file was not copied"
done < "$csv"
echo "Finished"

这样,脚本将告诉您任何未成功复制的文件。

如果您只想在脚本末尾打印错误,可以将错误的文件名保存在变量中,并在循环完成后打印它:

while IFS=, read -r file rest
do
  find "$sourcefolder" -name "$file" -exec cp '{}' "$destfolder" \;
  ## Check if the file was copied
  [[ -e "$destfolder/$file" ]] || badfiles=$(printf "%s\n%s" "$file" "$badfiles")
done < "$csv"

## Check if all the files were correctly copied
if [[ -z "$badfiles" ]]; then
        echo "All files were succesfuly copied."
else
        printf 'Some files were not copied:\n%s\n' "$badfiles"
fi

您还可以扩展它以避免覆盖同名的文件:

while IFS=, read -r file rest
do
  find "$sourcefolder" -name "$file" -print0 |
    while IFS= read -d '' -r filepath; do
     c="";
     while [[ -e "$destfolder/$file$c" ]]; do
       ((c++))
     done
     cp "$filepath" "$destfolder/$file$c"
  done
  ## Check if the file was copied
  [[ -e "$destfolder/$file" ]] || badfiles=$(printf "%s\n%s" "$file" "$badfiles")
done < "$csv"

## Check if all the files were correctly copied
if [[ -z "$badfiles" ]]; then
        echo "All files were succesfuly copied."
else
        printf 'Some files were not copied:\n%s\n' "$badfiles"
fi

如果 csv 中的文件名可以包含换行符,此操作将会失败。如果可能的话,请将第一个while循环更改为:

while IFS= read -d"," -r file rest; do ...

但请注意,如果 csv 的任何行只包含文件名(因此没有逗号),则此操作将会失败。你不能同时使用这两种方法,如果你可以有没有逗号的行,请使用第一个版本,如果你可以有带换行符的文件名,请使用第二个版本。

答案2

  1. 你的循环是不正确的,因为你什么也没做rest

  2. 作为特登建议在每次复制后检查,而不是在循环后检查一次

  3. 否定文件检查的存在,以获得正确的注释
  4. 并注意特登的警告,如果源树中有相同名称的文件,则您在目标中只会获得一份副本。

尝试这个,

while read -d, -r file
do
   find $sourcefolder -name "${file}" -exec cp '{}' $destfolder \;
   ## Check if the file was copied
   [[ ! -e "$destfolder/$file" ]] && echo "File $file was not copied"
done < "$csv"
echo "Finished"

更新:

如果您的 CSV 是这样的,则此解决方案有效

fileA,fileB,fileC,fileD, ...

但是,既然您说 terdon 的解决方案有效,您的文件必须如下所示

fileA,valueA1,valueA2,valueA3
fileB,valueB1,valueB2,valueB3
fileC,valueC1,valueC2,valueC3
fileD,valueD1,valueC2,valueD3

文件名之后的其余行将被简单地丢弃。

相关内容