-exec 찾기 및 카운터/진행 증가

-exec 찾기 및 카운터/진행 증가

간단히 말해서:

Q: 카운터 find -exec루핑을 유지하려면 어떻게 해야 합니까?


내 사용 사례:

여기저기 흩어져 있는 디렉토리를 많이 옮겨야 해서 이렇게 했습니다.

find . -type d -name "prefix_*" \
    -exec sh -c '
        new_path="/new/path/$(basedir "$1")";
        [ -d "$new_path" ] || mv "$1" "$new_path";
    ' find_sh {} \;

(실제 명령은 그것을 구성하는 요소에 대한 일부 메타데이터를 읽었기 때문에 더 복잡합니다 /new/path. 어쨌든 명령 자체에 대해 논쟁하고 싶지는 않습니다. 이는 질문의 일부가 아니라 사용 사례일 뿐입니다.)

잘 작동하지만 시간이 꽤 오래 걸리므로 진행 상황을 추적하고 싶습니다.

그래서 파일에 쓸 카운터를 추가했습니다.

i=$(cat ~/find_increment || echo 0);
echo $((i+1)) | tee ~/find_increment;

이것도 훌륭하게 작동하지만 다음과 같은 느낌이 듭니다.진짜약 100,000개의 디스크 읽기 및 쓰기 작업을 수행하는 것은 좋지 않은 생각입니다.

디스크 대신 쓰기를 고려했지만 ramdisk이 작업을 수행하는 데 필요한 환경에는 해당 옵션이 없습니다.

실행 사이에 카운터를 유지하는 더 좋은 방법이 있습니까 -exec?

답변1

findfind순수한 명령을 사용하는 대신 루프나 GNU 와 while read결합 할 수 있습니다 parallel. 발견 된 모든 경로에 대해 새 쉘을 시작할 필요가 없기 때문에 둘 다 아마도 둘 중 하나보다 더 빠를 것입니다 find.-execfind

GNU Parallel을 사용한 솔루션

GNU와 비교하면 다음과 parallel같은 장점이 있습니다 while read.

  • 올바른 결과를 얻는 것이 더 쉽습니다. 아니요 IFS=, 또한 -r필수입니다.
  • 내장된 작업 번호 변수 {#}.
    보다 편리한 문자열 교체를 확인하려면 다음을 확인하세요.지도 시간.
  • 필요한 경우 쉽게 병렬화할 수 있습니다.
    제거되면 -j1기본적으로 코어 수만큼 작업자 스레드를 갖게 됩니다.
script='
    echo Processing job number {#}
    new_path="/new/path/$(basedir {})"
    [ -d "$new_path" ] || mv {} "$new_path"
'
find … -print0 | parallel -0 -j1 "$script"

는 에서 읽은 올바르게 참조된 항목 {}으로 대체 됩니다 . 다시 인용 하지 마십시오 .parallelstdin{}

parallel스크립트를 시작한 것과 동일한 셸을 사용하여 스크립트를 실행합니다. 스크립트 에서 함수를 parallel사용하기 시작하면 .bashbash

"읽으면서 읽기"를 사용하는 솔루션

find … -print0 |
while IFS= read -r -d '' old_path; do
    echo Processing job number "$((++job))"
    new_path="/new/path/$(basedir "$old_path")"
    [ -d "$new_path" ] || mv "$old_path" "$new_path"
done 

답변2

가능하다면 거기에 카운터를 저장하여 /dev/shm/디스크 쓰기를 방지하세요.

=> /dev/shm/find_increment대신 사용하세요 ~/find_increment.

관련 정보