다음 명령을 고려하십시오.
find . -type f -name '*.*' -exec mv '{}' '{}_foo' \;
find
이 경우 무한 루프를 방지하는 방법은 무엇입니까?
한편으로, 나는 그 발견을 아는 것이아니요쉘 글로브처럼 작동합니다. 즉, *.jpg
모든 파일의 목록을 가져오는 것이 아니라 내부적으로 목록을 저장한 다음 처리합니다.목록 항목. 대신, 기본 운영 체제에서 파일을 "증분적으로" 처리하여 각 파일이 알려지자마자 처리합니다(질문과 관련이 없으므로 발생할 수 있는 특정 양의 버퍼링은 무시합시다). 결국, 내가 아는 한, 이것이 find
많은 파일을 포함하는 디렉토리의 glob에 비해 가장 큰 장점입니다.
이것이 사실이라면 find가 어떻게 무한 루프를 방지하는지 이해하고 싶습니다. 위의 예에서 1.jpg
이름 바꾸기는 1.jpg_foo
StackOverflow 및 다른 곳의 토론에서 이름을 바꾸면 파일(이름)이 디렉터리의 파일 목록에서 다른 위치를 차지할 수 있으므로 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가 두 번째로 실행될 위험이 항상 있으므로 어느 쪽이든 적절한 보호 조치를 취해야 합니다.