【问题标题】:Intersection of three files三个文件的交集
【发布时间】:2018-08-27 09:57:06
【问题描述】:

我的互联网连接不佳,并尝试下载三倍相同的 rar 存档 (> 500 Mo)。每个文件都已损坏,但我希望可以在三个损坏的交集处创建第四个没有任何损坏的文件。
我对 diff 或 comm 不满意,不知道是否可以用它来做我想做的事。
感谢您的帮助!

【问题讨论】:

  • 首先您应该检查所有三个文件是否彼此不同。如果文件相同,则原始文件已损坏。运行cmp 1.rar 2.rar cmp 2.rar 3.rar。如果根本没有输出,那么文件是相同的。
  • 很抱歉没有回答您的具体问题,但如果您使用可重新启动的下载来代替,您可能会获得更大的成功 - curl 和 wget 都支持重新启动,并将确保您最终拥有整个文件为你。 unix.stackexchange.com/questions/327372/…cyberciti.biz/tips/wget-resume-broken-download.html
  • 鉴于差异,您仍然必须知道哪一组字节是正确字节组。如果三个中的 2 个在给定部分上达成一致,则它们可能是正确的,但不一定,如果三个都不同,那么您所能做的就是猜测。

标签: linux bash rar


【解决方案1】:

按照 cmets 中 chepner 的想法,我将如何重建 可能的原件。

#!/bin/bash

FILE1="$1"
FILE2="$2"
FILE3="$3"
RESFILE="$4"

diff_at() {
  POS=$(cmp "$1" "$2" -i $3 | sed 's/,//' | cut -d ' ' -f 5)
  if [ "$POS" == "" ]; then
    POS=$(du -b "$1" "$2" | cut -f 1 | sort | head -n1) # min()
  fi
  echo $POS
}

max() {
  if [ $# -eq 0 ]; then # Degenerate case
    echo ""
  elif [ $# -eq 1 ]; then # Base case
    echo $(($1 + 0)) # Strings are interpreted as 0
  else
    V=$1
    shift
    M=$(max $@)
    echo $(($V > $M ? $V : $M))
  fi
}

# Shallow check of arguments
if [ $# -ne 4 ]; then
  echo "Provide three files to compare and a file to write output into."
  exit 1
fi

# If one of them is larger, you cannot compare its (probable) correctness
S1=$(du -b "$FILE1" | cut -f 1)
S2=$(du -b "$FILE2" | cut -f 1)
S3=$(du -b "$FILE3" | cut -f 1)
if [ $S1 -gt $S2 -a $S1 -gt $S3 -o $S2 -gt $S1 -a $S2 -gt $S3 -o $S3 -gt $S2 -a $S3 -gt $S1 ]; then
  echo "$0: Unable to reconstruct original file."
  exit 1
fi
FILESIZE=$(max $S1 $S2 $S3)

# The idea is that of extracting and appending the common part
truncate -s 0 "$RESFILE" # This will overwrite existing output
BIAS=0
while [ $BIAS -lt $FILESIZE ]; do
  I12=$(diff_at "$FILE1" "$FILE2" $BIAS)
  I23=$(diff_at "$FILE2" "$FILE3" $BIAS)
  I31=$(diff_at "$FILE3" "$FILE1" $BIAS)

  # Unreconstructible, aka all of them differ at the same byte
  if [ $I12 -eq $I23 -a $I12 -eq $I31 ]; then
    echo "$0: Unable to reconstruct original file."
    break;
  fi

  # Biggest common part
  MAXBYTE=$(max $I12 $I23 $I31)

  # Exclude the file with wrong byte
  if [ $I12 -eq $MAXBYTE -o $I31 -eq $MAXBYTE ]; then
    tail -c+$(($BIAS + 1)) "$FILE1" | head -c $(($MAXBYTE - 1)) >> "$RESFILE"
  else
    tail -c+$(($BIAS + 1)) "$FILE2" | head -c $(($MAXBYTE - 1)) >> "$RESFILE"
  fi

  # Update position
  BIAS=$(($BIAS + $MAXBYTE - 1))
done

为了处理“猜测”(同一位置的所有三个字节不同),您需要提交对脚本的更改。

从很多角度来看,我认为有比上述更好的选择,所以请把它看作是又快又脏的选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-02
    • 2023-03-06
    • 2017-03-06
    • 1970-01-01
    • 1970-01-01
    • 2020-01-24
    • 2012-09-29
    • 1970-01-01
    相关资源
    最近更新 更多