如何使用 bash 将不完整的文件替换为原始文件

如何使用 bash 将不完整的文件替换为原始文件

我有 2 个目录,其中都有许多不同的子目录。

其中“一半”提取的.mkv文件是由另一个程序导入的。

.mkv中包含原始的完全提取的文件。


我正在尝试编写一个 bash 脚本来用原始文件替换损坏的 .mkv 文件。两个目录中的文件名相同,但子目录和文件大小不同。


我尝试编写或更改许多涉及findfdupes和的解决方案grep

但我就是无法让它发挥作用。有人可以帮助我吗?


不完整的例子

#!/bin/bash

dirname1=/mnt/raid1/dir1
dirname2=/mnt/raid1/dir2
find $dirname1 -name '*.mkv'
while read fileName
do
find $dirname2 -type f | grep "$fileName"
done

答案1

如果文件名相同,只需使用mv即可解决问题:

# traverse the original's directory
for o in original/*/*.mkv; do
  # traverse the corrupted's directory
  for c in corrupted/*/*.mkv; do 
    # if a corrupted file has the same name as an original's
    # perform the `mv` command replacing the former
    if [[ "$(basename "$o")" = "$(basename "$c")" ]]; then
      mv -- "$o" "$c"; 
    fi
  done
done

双破折号--意思是:

准则 10:第一个--非选项参数的参数应被接受为表示选项结束的分隔符。任何后续参数都应被视为操作数,即使它们以 '-' 字符开头。

-i您可以使用在覆盖文件之前提示问题的选项...如果您有数千个文件,这可能会很麻烦。

mv -i -- "$o" "$c"
mv: overwrite 'corrupted/<sub dir>/filename.mkv'?

笔记:一般来说,在执行此类覆盖/删除操作之前最好对数据进行备份。

答案2

zsh而不是bash

#! /bin/zsh -
zmodload zsh/stat || exit

orig_dir=/mnt/raid1/dir1
incomplete_dir=/mnt/raid1/dir2

typeset -A where size

for f in $orig_dir/**/*.mkv(ND.); do
  stat -A s +size -- $f || continue
  if (( $+where[$f:t] )); then
    print -ru2 -- "$f:t is found in more than one place ($where[$f:t] and $f at least)!"
    exit 1
  fi
  where[$f:t]=$f size[$f:t]=$s
done

# for dry-run (comment out when happy)
cp() (PS4='Would run'; set -x; : cp "$@")

ret=0
for f in $incomplete_dir/**/*.mkv(ND.); do
  stat -A s +size -- $f || continue
  if (( $size[$f:t] > $s )); then
    cp -- $where[$f:t] $f || ret=$?
  fi
done
exit $ret

(未经测试)。

要仅添加文件的缺失部分而不是复制整个文件,您可以执行以下操作:

zmodload zsh/system
resume() {
  {
    sysseek -w end -u 1 0 &&
      sysseek -w start -u 0 $(( systell(1) )) &&
      cat
  } < $1 1<> $2
}

resume代替上面使用cp --

相关内容