[linux] rm, cp, mv 명령의 인수 목록이 너무 깁니다.

UNIX의 디렉토리에 수백 개의 PDF가 있습니다. PDF 이름은 실제로 길다 (약 60 자).

다음 명령을 사용하여 모든 PDF를 함께 삭제하려고 할 때 :

rm -f *.pdf

다음과 같은 오류가 발생합니다.

/bin/rm: cannot execute [Argument list too long]

이 오류에 대한 해결책은 무엇입니까? 이 오류가 mvcp명령에도 발생합니까 ? 그렇다면 이러한 명령을 해결하는 방법은 무엇입니까?



답변

이것이 발생하는 이유는 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 주석 ).

참고 문헌


답변

find-delete조치를 :

find . -maxdepth 1 -name '*.pdf' -delete


답변

또 다른 대답은 xargs명령을 일괄 처리 하도록 강제 하는 것입니다. 예를 들어 한 번에 delete파일 100cd디렉토리에 넣고 다음을 실행하십시오.

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 스크립트를 복사하여 실행하십시오.

보안상의 이유로이 모든 것.