[linux] rm, cp, mv 명령의 인수 목록이 너무 깁니다.
UNIX의 디렉토리에 수백 개의 PDF가 있습니다. PDF 이름은 실제로 길다 (약 60 자).
다음 명령을 사용하여 모든 PDF를 함께 삭제하려고 할 때 :
rm -f *.pdf
다음과 같은 오류가 발생합니다.
/bin/rm: cannot execute [Argument list too long]
이 오류에 대한 해결책은 무엇입니까? 이 오류가 mv
및 cp
명령에도 발생합니까 ? 그렇다면 이러한 명령을 해결하는 방법은 무엇입니까?
답변
이것이 발생하는 이유는 bash가 실제로 별표를 일치하는 모든 파일로 확장하여 매우 긴 명령 행을 생성하기 때문입니다.
이 시도:
find . -name "*.pdf" -print0 | xargs -0 rm
경고 : 이것은 재귀 검색이며 하위 디렉토리에서도 파일을 찾아 삭제합니다. 압정 -f
당신은 당신이 확인을하지 않을 경우에만 rm 명령에.
다음을 수행하여 명령을 비재 귀적으로 만들 수 있습니다.
find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm
또 다른 옵션은 find의 -delete
플래그 를 사용하는 것입니다 .
find . -name "*.pdf" -delete
답변
tl; dr
명령 행 인수의 크기에 대한 커널 제한 사항입니다. for
대신 루프를 사용하십시오 .
문제의 기원
이것은 시스템 문제이며 관련이 execve
있고 ARG_MAX
일정합니다. 그것에 대해 문서를 많이합니다 (이 남자는 execve , 데비안의 위키 ).
기본적으로 확장 은 한계 를 초과 하는 명령 (매개 변수 포함)을 생성합니다 ARG_MAX
. 커널 2.6.23
에서 한계는로 설정되었습니다 128 kB
. 이 상수는 증가했으며 다음을 실행하여 값을 얻을 수 있습니다.
getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic
솔루션 : for
루프 사용
BashFAQ / 095for
에서 권장 되는 루프를 사용 하고 RAM / 메모리 공간을 제외하고 제한이 없습니다.
드라 이런을 실행하면 예상 한 내용이 삭제됩니다.
for f in *.pdf; do echo rm "$f"; done
그리고 그것을 실행하십시오 :
for f in *.pdf; do rm "$f"; done
또한 glob가 쉘 사이에서 강력하고 일관된 동작을 갖기 때문에 이식 가능한 접근 방식 입니다 (POSIX 사양의 일부 ).
참고 : 여러 의견에서 언급했듯이 더 복잡한 시나리오 ( 예 : 하나 이상의 작업을 수행하려는 경우)를 적용 할 수 있기 때문에 실제로는 더 느리지 만 유지 관리 가 용이합니다.
솔루션 : 사용 find
주장한다면, xargs 는 “NUL- 구분되지 않은 입력을 읽을 때 위험 (파손, 악용 가능 등)”이므로 사용할 수는 find
없지만 실제로 는 사용하지 않습니다 .
find . -maxdepth 1 -name '*.pdf' -delete
사용 -maxdepth 1 ... -delete
대신하는 것은 -exec rm {} +
허용 find
단순히 때문에 빠르고, 외부 프로세스를 사용하지 않고 (덕분에 필요한 시스템 호출 자체를 실행하는 @chepner 주석 ).
참고 문헌
- “인수 목록이 너무 깁니다”가 표시됩니다. 큰 목록을 청크로 처리하려면 어떻게해야합니까? @ wooledge
- execve (2)-Linux 매뉴얼 페이지 (ARG_MAX 검색);
- 오류 : 인수 목록이 너무 @ @ 데비안 위키;
- 인용 인수를 전달할 때 왜“/ bin / sh : 인수 목록이 너무 깁니다”가 표시됩니까? @ 슈퍼 유저
답변
find
이 -delete
조치를 :
find . -maxdepth 1 -name '*.pdf' -delete
답변
또 다른 대답은 xargs
명령을 일괄 처리 하도록 강제 하는 것입니다. 예를 들어 한 번에 delete
파일 100
로 cd
디렉토리에 넣고 다음을 실행하십시오.
echo *.pdf | xargs -n 100 rm
답변
또는 시도해 볼 수 있습니다.
find . -name '*.pdf' -exec rm -f {} \;
답변
한 번에 매우 많은 수의 파일을 삭제하려고하면 (오늘 485,000+ 이상의 디렉토리를 삭제 한 경우) 다음 오류가 발생할 수 있습니다.
/bin/rm: Argument list too long.
문제는 당신이 무언가 같이 입력 할 때이다 rm -rf *
의는 *
“RF RM은 파일 1 파일 2 파일 3 file4″등등과 같은 모든 일치하는 파일의 목록으로 대체됩니다. 이 인수 목록을 저장하기 위해 할당 된 비교적 작은 메모리 버퍼가 있으며, 채워지면 쉘은 프로그램을 실행하지 않습니다.
이 문제를 해결하기 위해 많은 사람들이 find 명령을 사용하여 모든 파일을 찾고 다음과 같이 “rm”명령으로 하나씩 전달합니다.
find . -type f -exec rm -v {} \;
내 문제는 500,000 개의 파일을 삭제해야하고 너무 오래 걸리는 것입니다.
파일을 삭제하는 훨씬 빠른 방법을 발견했습니다.“find”명령에는“-delete”플래그가 내장되어 있습니다! 내가 사용한 결과는 다음과 같습니다.
find . -type f -delete
이 방법을 사용하여 초당 약 2000 파일의 속도로 파일을 삭제했습니다.
파일 이름을 삭제하면서 파일 이름을 표시 할 수도 있습니다.
find . -type f -print -delete
… 또는 삭제할 파일 수를 표시 한 다음 삭제하는 데 걸리는 시간도 표시합니다.
root@devel# ls -1 | wc -l && time find . -type f -delete
100000
real 0m3.660s
user 0m0.036s
sys 0m0.552s
답변
당신은 이것을 시도 할 수 있습니다 :
for f in *.pdf
do
rm $f
done
편집 : ThiefMaster 의견은 나에게 그런 위험한 습관을 어린 껍질의 제디에게 공개하지 말 것을 제안합니다. 그래서 더 많은 “safer”버전을 추가 할 것입니다 (누군가 “-rf. ..pdf”파일이있을 때 물건을 보존하기 위해)
echo "# Whooooo" > /tmp/dummy.sh
for f in '*.pdf'
do
echo "rm -i $f" >> /tmp/dummy.sh
done
위를 실행 한 후 즐겨 찾기에서 /tmp/dummy.sh 파일을여십시오. 편집기에서 모든 한 줄에 위험한 파일 이름이 있는지 확인하고 발견되면 주석 처리하십시오.
그런 다음 작업 디렉토리에 dummy.sh 스크립트를 복사하여 실행하십시오.
보안상의 이유로이 모든 것.