![Bash 스크립트를 사용하여 중복 파일 찾기](https://linux55.com/image/181668/Bash%20%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC%20%EC%A4%91%EB%B3%B5%20%ED%8C%8C%EC%9D%BC%20%EC%B0%BE%EA%B8%B0.png)
동일한 ext4 파일 시스템의 현재 작업 디렉토리에서 동일한 내용, 권한 및 소유자를 가진 바이너리 파일을 반복적으로 찾고 해당 파일에 대한 하드 링크가 있는 이전 액세스 시간으로 모두 바꾸는 bash 단일 라이너를 작성하는 방법 최근에 액세스한 파일 및 보고서 디스크 공간이 킬로바이트 단위로 절약됩니까?
지금까지 달성한 것만으로는 목표를 달성하기에 충분하지 않습니다.
#! /bin/sh
fdupes -r -p -o 'time' . | xargs file -i | grep binary | awk '{print $1}' | awk '{print substr($0,3)}' | sed 's/.\{1\}$//' | xargs rdfind -makehardlinks true
답변1
hardlink
모든 요구 사항을 충족할 수는 없지만 하드 링크를 만드는 데 사용할 수 있습니다. 디렉터리뿐만 아니라 파일 인수도 허용할 수 있으며 항상 동일한 파일 집합을 첫 번째 파일에 순차적으로 연결하는 것 같습니다. 또한 크기가 0인 파일도 무시합니다.
fdupes
필요한 것을 정확하게 선택하지만 실제 파일 매개변수를 출력하는 대신 동일한 파일 그룹과 함께 단락 모드 출력을 출력합니다. 각 그룹은 빈 줄로 끝납니다.
따라서 정확한 선택 항목이 하드 링크되도록 하려면 각 단락을 개별적으로 호출 fdupes
해야 합니다 hardlink
. 소유자가 다르거나 권한이 다른 두 쌍의 동일한 개체가 존재하는 상황을 피하세요. 물론 파일에 포함된 바이너리 파일은 필터링되어야 합니다.
#!/bin/bash
unset arr i
while IFS= read -r f; do
# move file to array if binary
if file -i "$f" | grep -q "charset=binary"; then
arr[++i]="$f"
fi
# if end of paragraph and array has files, hardlink and unset array
if [[ "$f" == "" && "${arr[@]}" ]]; then
printf "\n => Hardlink for %d files:\n" "$i"
hardlink -n -c -vv "${arr[@]}"
unset arr i
fi
done < <(fdupes -rpio time .)
hardlink
with -n
매개변수는 아무것도 시뮬레이션하고 쓰지 않으므로 위의 내용을 있는 그대로 테스트하고 -n
나중에 제거하세요.
또한 줄바꿈이 포함된 파일 이름은 처리되지 않으므로 공백을 사용한 테스트는 괜찮은 것 같습니다.
답변2
드디어 원하는 결과를 얻었습니다. @thanasisp 감사합니다. 이렇게 하려면 fdupes와 rdfind라는 두 가지 프로그램이 필요합니다.
#!/bin/bash
unset arr i; while IFS= read -r f; do if file -i "$f" | grep -q "charset=binary"; then arr[++i]="$f"; fi; if [[ "$f" == "" && "${arr[@]}" ]]; then printf "\n => Hardlink for %d files:\n" "$i";rdfind -makehardlinks true "${arr[@]}" | grep "Total size is" | grep -P "[0-9]+" -o | head -1 | awk -v count="$i" '{print $1/count;}' | awk '{printf("%s kibibytes saved.\n",$1/1024)}'; unset arr i; fi; done < <(fdupes -rpio time .)