find는 무한 루프(예: 파일을 찾는 동안 파일 이름이 변경되는 경우)를 어떻게 방지합니까? [복사]

find는 무한 루프(예: 파일을 찾는 동안 파일 이름이 변경되는 경우)를 어떻게 방지합니까? [복사]

다음 명령을 고려하십시오.

find . -type f -name '*.*' -exec mv '{}' '{}_foo' \;

find이 경우 무한 루프를 방지하는 방법은 무엇입니까?

한편으로, 나는 그 발견을 아는 것이아니요쉘 글로브처럼 작동합니다. 즉, *.jpg모든 파일의 목록을 가져오는 것이 아니라 내부적으로 목록을 저장한 다음 처리합니다.목록 항목. 대신, 기본 운영 체제에서 파일을 "증분적으로" 처리하여 각 파일이 알려지자마자 처리합니다(질문과 관련이 없으므로 발생할 수 있는 특정 양의 버퍼링은 무시합시다). 결국, 내가 아는 한, 이것이 find많은 파일을 포함하는 디렉토리의 glob에 비해 가장 큰 장점입니다.

이것이 사실이라면 find가 어떻게 무한 루프를 방지하는지 이해하고 싶습니다. 위의 예에서 1.jpg이름 바꾸기는 1.jpg_fooStackOverflow 및 다른 곳의 토론에서 이름을 바꾸면 파일(이름)이 디렉터리의 파일 목록에서 다른 위치를 차지할 수 있으므로 find가 파일을 다시 만날 수 있다는 것을 알고 있습니다. 그런 다음 이름을 바꿉니다. 다시 (에 1.jpg_foo_foo) 등등.

분명히 이런 일은 일어나지 않을 것입니다.

답변1

단일 디렉터리에서는 처리하기 전에 전체 파일 목록을 읽는 것만큼 간단할 수 있습니다(그리고 strace무슨 일이 일어났는지 보이게 만드는 것).

# keep reading entries first
openat(AT_FDCWD, ".", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_DIRECTORY) = 4
getdents(4, /* 1024 entries */, 32768)  = 32752
getdents(4, /* 1024 entries */, 32768)  = 32768
getdents(4, /* 426 entries */, 32768)   = 13632
getdents(4, /* 0 entries */, 32768)     = 0
close(4)                                = 0

(가독성을 위해 출력이 요약됨)

# process stuff later
clone(...
wait4(...
--- SIGCHLD...
clone(...
wait4(...
--- SIGCHLD ...

그러나 일반적으로 말하면 find루프가 전혀 차단되지 않습니다. 파일을 하위 디렉터리로 이동하면 이런 일이 여러 번 발생합니다.

mkdir -p sub/sub/sub/sub
find -type f -exec mv {} sub/{}_foo \;

sub/sub/sub/sub/file_foo_foo_foo_foo이로 인해 이와 같은 일이 발생할 수 있습니다 . ( -depth이 경우 도움이 될 수 있습니다).

find존재하지도 않는 마법을 맹목적으로 사용하는 것보다 충돌 가능성을 처음부터 피하는 것이 좋습니다 . 편집하기 전에 질문하신 내용은 이름이 바뀐 파일과 전혀 일치하지 않기 때문에 좋은 해결 방법입니다.

엄격한 요구 사항이 없더라도 파일을 두 번 처리할 수 없으며 처리해서는 안 된다는 점을 분명히 하는 것이 가장 좋습니다. 여기서는 파일 jpg대신 파일 이름을 바꿉니다 foo.

또한 find단일 호출로 파일이 두 번 처리되는 것을 방지하더라도 전체 스크립트가 다시 실행되고 find가 두 번째로 실행될 위험이 항상 있으므로 어느 쪽이든 적절한 보호 조치를 취해야 합니다.

관련 정보