我有 2 个目录,其中都有许多不同的子目录。
其中“一半”提取的.mkv
文件是由另一个程序导入的。
秒.mkv
中包含原始的完全提取的文件。
我正在尝试编写一个 bash 脚本来用原始文件替换损坏的 .mkv 文件。两个目录中的文件名相同,但子目录和文件大小不同。
我尝试编写或更改许多涉及find
、fdupes
和的解决方案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 --
。