sha1sum의 임의 문자를 사용하여 파일 이름을 바꿉니다. 이름이 독특할까요?

sha1sum의 임의 문자를 사용하여 파일 이름을 바꿉니다. 이름이 독특할까요?

이 명령을 사용하여 임의의 문자로 파일 이름을 바꾸고 sha1sum모든 파일을 하위 디렉터리에서 현재 디렉터리로 이동합니다.

for fname in `find . -type f`; do mv "$fname" $(echo "$fname" | sha1sum | cut -f1 -d' ').html; done
  1. 하지만 문제는 이것이 고유한 파일 이름을 생성할 것인가입니다. sha1sum에 의해 생성된 이름이 고유하지 않을 수 있다는 점(두 번 이상 생성됨)이 걱정됩니다.
  2. 위 명령을 실행한 다음 다른 디렉터리에서 다른 명령을 실행하면 각 파일에 대해 고유한 파일 이름이 생성됩니까?

답변1

sha1sum입력이 고유한 한 출력도 고유합니다. (매우 운이 좋지 않아 sha1sum충돌이 발생하지 않는 한)

사용 사례의 경우 printf '%s' "$fname"대신 사용하는 것이 좋은 습관입니다 . echo "$fname"전자는 $fnameis -n, 또는 ,... -e일 때 작동합니다. 또한보십시오엔조팁 비고, 언뜻보기에 놓쳤습니다.

또한 귀하의 동기가 무엇인지 잘 모르겠지만 sha1sum파일 이름 대신 파일 콘텐츠 제공을 고려할 수도 있습니다. 이렇게 하면 각 고유한 콘텐츠에 대한 고유한 파일 이름을 얻을 수 있습니다.

답변2

먼저, 몇 가지 쉘 질문:

  • for fname in `find …`파일 이름이 손상되고 이름이 너무 긴 파일이 너무 많으면(명령줄이 너무 길기 때문에) 실패하므로 사용하지 마십시오 . 대신 사용하십시오 find -exec. 실행된 명령에는 쉘 확장이 필요하므로 find,쉘 호출.
  • "$fname"명령 대체와 변수 대체를 큰따옴표( , ) 로 묶어야 합니다 "$(echo …)".
  • echo일부 쉘에서 백슬래시를 분리합니다( 로 시작하는 일부 인수도 분리 -하지만 모든 인수가 로 시작하므로 문제가 되지 않습니다 ./). 문자열을 문자 그대로 인쇄하는 한 가지 방법은 마지막 개행 문자를 피하기 위해 printf "%s\n" "$fname", 또는 "$fname"입니다. printf "%s"여기서는 파일 이름의 해시 대신 파일 이름의 해시와 마지막 개행 문자를 사용할 이유가 없습니다.

그래서 우리는 다음 명령을 얻습니다:

find . -type f -exec sh -c 'mv "$0" "$(printf "%s" "$0" | sha1sum | cut -f1 -d" ").html' {} \;

한 번에 전체 이름 배치에 대해 셸을 호출하는 것이 약간 더 빠릅니다.

find . -type f -exec sh -c 'for fname; do mv "$fname" "$(printf "%s" "$fname" | sha1sum | cut -f1 -d" ").html; done' _ {} +

이 접근 방식의 한 가지 문제점은 디렉터리 탐색이 완료되기 mv전에 작업을 시작 하면 find이미 이동된 파일이 이동될 수 있다는 것입니다 . 이는 파일 이동을 시작하기 전에 완료될 때까지 기다리기 mv때문에 명령에 문제가 되지 않습니다. find. 따라서 이름이 바뀐 파일을 다른 디렉터리 계층 구조에 배치하십시오. 이렇게 하면 제안한 명령의 또 다른 문제, 즉 mv호출되는 항목을 재정의할 수 있는 가능성이 해결됩니다 <sha1sum>.html.

mkdir ../staging
find . -type f -exec sh -c 'for fname; do mv "$fname" ../staging/"$(printf "%s" "$fname" | sha1sum | cut -f1 -d" ").html; done' _ {} +
find . -depth \! -name "." -type d -exec rmdir {} +
mv ../staging/* .

이제 주요 질문에 답해 보겠습니다. 경로가 다른 두 파일은 두 개의 다른 SHA-1 해시에 매핑됩니다. 수학적으로 말하면 동일한 SHA-1 해시 값을 가진 다른 문자열이 있습니다(문자열은 무한히 많지만 해시 수는 유한하므로 이는 분명합니다). 그러나 실제로는 이를 찾는 방법을 아는 사람이 없습니다. SHA-1에는 알려진 충돌이 없습니다. 언젠가는 SHA-1이 손상될 수 있으며, 이 경우 프로그램은 악의적인 공격이 아닌 우발적인 충돌에 대해서만 안전할 것입니다. 이런 일이 발생하면(곧 발생하지 않음) 당시 안전하다고 간주되는 해싱 알고리즘으로 업그레이드해야 합니다.

두 번째 질문의 경우 해시 값은 전적으로 해시한 문자열에 의해 결정됩니다. 따라서 이름이 지정된 두 개의 파일이 있고 각 디렉터리에서 이름 바꾸기 프로세스를 차례로 실행 tweedledum/staple하면 tweedledee/staple두 디렉터리 모두 이름이 . 디렉터리 이름과 같은 텍스트입니다.tweedledeetweedledum1c0ee9c1eed005a476403c7651b739ae5bc7cf2a.html

답변3

먼저 교체를 제안합니다

for fname in `find . -type f`; do

그리고

find . -type f | while read -r fname; do

다음으로 sha1sum은 "거의" 고유해야 합니다. 즉, 서로 다른 파일이 동일한 체크섬을 가질 확률이 상당히 낮으므로 고유하다고 안전하게 가정할 수 있습니다.

관련 정보