중복된 콘텐츠가 포함된 텍스트 파일을 찾고 계십니까?

중복된 콘텐츠가 포함된 텍스트 파일을 찾고 계십니까?

수천 개의 파일을 처리하는 스크립트의 출력을 덮어쓰는(>) 대신 실수로 추가(>>)했지만 파일의 약 20%에 대해서만 이 작업을 수행했습니다(스크립트의 병렬 인스턴스를 5개 실행했습니다). 기본적으로 10줄의 텍스트, 빈 줄, 그리고 다시 동일한 10줄의 텍스트가 있습니다.

  1. 이 파일을 어떻게 찾을 수 있나요?
  2. 두 번째 반복을 어떻게 삭제합니까?

1이 2보다 훨씬 더 중요합니다.

수천 개의 파일을 처리하는 스크립트의 출력을 덮어쓰는(>) 대신 실수로 추가(>>)했지만 파일의 약 20%에 대해서만 이 작업을 수행했습니다(스크립트의 병렬 인스턴스를 5개 실행했습니다). 기본적으로 10줄의 텍스트, 빈 줄, 그리고 다시 동일한 10줄의 텍스트가 있습니다.

  1. 이 파일을 어떻게 찾을 수 있나요?
  2. 두 번째 반복을 어떻게 삭제합니까?

1이 2보다 훨씬 더 중요합니다.

(이 질문은 문제를 보여줍니다)


고쳐 쓰다:

내용을 꼼꼼히 살펴봤습니다. 중복된 내용이 포함된 파일의 구조는 다음과 같습니다.

<empty line>
<text>
<empty line>
<empty line>
<same text>
<empty line>

중복된 내용이 없는 파일은

<empty line>
<text>
<empty line>

즉, 가운데에 두 개의 빈 줄이 있는 것입니다. 첫 번째 줄의 시작점은 위의 텍스트이고, 두 번째 줄의 시작점은 아래의 텍스트입니다. 텍스트의 상단과 하단은 빈 줄로 둘러싸여 있습니다.

답변1

  1. 다른 작업을 수행하기 전에 현재 데이터를 백업하십시오. 문제가 발생하면 언제든지 이 복사본으로 되돌릴 수 있습니다. 예를 들어 다음을 사용할 수 있습니다 tar.

    tar cfz /path/to/backup-files.tar.gz /path/to/directory-to-backup/
    

    일반적으로 다음과 같이 해야 합니다.안 돼요관심 있는 모든 데이터의 고유한 복사본을 처리하세요. 반드시 백업을 해두시거나, 복사본을 만들어서 작업하시기 바랍니다. 즉, 당신은해야합니다언제나변경 사항을 되돌리고 실수를 취소할 수 있는 쉽고 빠른 방법을 스스로에게 제공하십시오.

  2. \n"좋은" 파일에 3번 연속으로 개행 문자( )가 나오지 않을 것이라고 확신한다면 다음을 시도해 보십시오.복사일부 "좋은" 파일과 "나쁜" 파일:

    perl -i -0777 -p -e 's/\n{3,}.*/\n\n/' filenames
    

    이렇게 하면 3개의 줄 바꿈(예: 텍스트 줄 끝에 있는 줄 바꿈과 두 개의 빈 줄이 뒤따름)에서 파일 끝까지의 모든 내용이 제거되고 두 개의 줄 바꿈(한 줄은 텍스트 줄 끝)으로 대체됩니다. 파일 끝에 추가하려는 빈 줄).

    모든 파일아니요3개의 연속된 줄 바꿈(즉, 복구할 필요가 없는 "좋은" 파일)이 있으며 수정되지 않습니다.

  3. 방금 Perl로 처리한 파일("좋음" 및 "나쁨")을 확인하십시오.

    예상과 일치하면 파일이 포함된 디렉터리의 모든 파일에 대해 Perl 스크립트를 실행합니다. 예를 들어, find모든 파일에 .txt확장명이 있는 경우:

    find /path/to/directory -type f -name '*.txt' -exec \
      perl -i -0777 -p -e 's/\n{3,}.*/\n\n/' {} +
    

    ( find실제 디렉토리와 파일 이름에 맞게 명령을 조정하십시오)

답변2

파일을 찾으려면 다중 문자 RS 및 ENDFILE에 GNU awk를 사용하십시오.

$ awk -v RS='\n{2}' '$0==p{f=1} {p=$0} ENDFILE{print FILENAME, (f ? "dups" : "uniq"); p=f=""}' file1 file2
file1 dups
file2 uniq

위의 내용은 이 입력에서 실행됩니다.

$ head file{1,2}
==> file1 <==

<text>


<text>


==> file2 <==

<text>

답변3

그리고 perl:

find . -type f -size +1c -exec perl -l -0777 -e '
  while (<<>>) {
    $size = length; $half = $size / 2;
    if ($size % 2 == 0 && substr($_, 0, $half) eq substr($_, $half)) {
      print "$ARGV is one of them";
      truncate $ARGV, $half or warn "truncate $ARGV: $!";
    }
  }' {} +

답변4

에서는 연관 배열을 zsh사용하여 파일 경로를 해당 내용에 매핑할 수 있습니다 . $mapfile이렇게 하면 첫 번째 절반과 두 번째 절반을 쉽게 비교하고 해당 위치에서 파일을 업데이트할 수 있습니다.

#! /bin/zsh -
zmodload zsh/mapfile || exit
set +o multibyte

for file in **/*(ND.L+1); do
  text=$mapfile[$file]
  size=$#text
  if (( size % 2 == 0 )); then # even size
    (( half = size / 2 ))
    if [[ $text[1,half] = $text[half+1,-1] ]]; then
      print -r -- $file is one of them
      mapfile[$file]=$text[1,half] # or truncate -s$half -- $file
    fi
  fi
done

(검증되지 않은).

**/*(ND.L+0)대신 **/*(ND.L+0m-1)지난 24시간(또는 지난 3시간 등) **/*(ND.mh-3)에 마지막으로 수정된 파일 만 처리 할 수 있습니다 . D숨겨진 파일이 더 이상 문제가 되지 않으면 삭제하세요. 제거되거나 주석 처리되어 mapfile[$file]=...일치하는 파일만 수정하지 않고 나열됩니다.

관련 정보