많은 수의 파일(400K+)을 한 디렉터리에서 다른 디렉터리로 이동하고 있으며 이를 수행하기 위한 다음 스크립트가 있습니다(mv 명령이 직접 작동하기에는 파일이 너무 많습니다).
for file in *;
do
mv $file ..
done
이 스크립트를 동시에 두 번(또는 그 이상) 실행하면 mv 명령이 동일한 파일에 액세스하려고 할 때 경쟁 조건이 발생합니까?
온라인으로 확인했지만 명확한 답변을 찾지 못했습니다. 감사해요!
답변1
경쟁 조건이 존재합니다(하지만 문제가 되지는 않습니다).
*
루프에 들어갈 때 확장하십시오. 이 스크립트의 두 번째 인스턴스를 동시에 실행하면 이동하려는 모든 파일이 이미 이동되었기 때문에 아무 작업도 수행되지 않을 수 있습니다. 이동 작업 중에 소스 디렉터리에 파일이 생성되지 않은 경우 오류 메시지가 가장 큰 문제입니다.
그러나 전반적으로 이 구조는 매우 나쁜 생각입니다. *
정렬된 목록으로 확장합니다. AFAIK 비활성화하는 것은 불가능합니다. 분명히 400K 파일의 경우 정렬하는 것만으로도 악몽입니다. man bash
"경로 이름 확장" 섹션을 참조하세요 .
단어 분할 후 bash는 -f 옵션이 설정되지 않은 한 각 단어에서 *, ? 및 [ 문자를 검색합니다. 이러한 문자 중 하나가 발생하면 해당 단어는 패턴으로 처리되고 패턴과 일치하는 파일 이름의 알파벳순 목록으로 대체됩니다.
mv
또한 한 번에 여러 파일을 이동할 수 있으므로 파일당 하나의 인스턴스를 실행해서는 안 됩니다 .
GNU 세계에서 더 나은 솔루션은 다음과 같습니다.
find . -mindepth 1 -maxdepth 1 -exec mv --target-directory=DIRECTORY {} +
답변2
더 나은 해결책은 다음을 사용하는 것입니다.GNU 병렬도착하다여러 매개변수 삽입. 기본적으로 Parallel은 n
작업을 동시에 실행하며 , n
그 수는 CPU의 코어 수입니다.
다음과 같이 많은 수의 파일을 이동할 때 다음 mv * destdir
과 같은 오류가 발생하는 경우가 있습니다.
bash: /bin/mv: Argument list too long
파일이 너무 많기 때문이죠. 다음을 수행할 수 있습니다.
ls -1 | parallel mv {} destdir
이는 mv
각 파일에 대해 실행됩니다. mv가 다음 줄과 일치하는 만큼의 인수를 취하면 더 빠르게 수행할 수 있습니다.
ls -1 | parallel -m mv {} destdir
옵션 -m
은 다음과 같습니다진짜파일을 병렬로 이동하거나 복사하는 것이 좋습니다.
-m Multiple arguments. Insert as many arguments as the command
line length permits. If multiple jobs are being run in
parallel: distribute the arguments evenly among the jobs.
Use -j1 to avoid this.
답변3
저처럼 parallel
구할 수 없는 분들을 위해
find source_dir -type f | xargs -n 1 -P 20 -I '{}' mv '{}' dest_dir/
-P
on 매개변수를 사용하여 프로세스 수를 정의할 수 있습니다 xargs
(위 예에서는 20으로 설정).