디렉토리의 모든 파일에 액세스하는 쉘 스크립트를 작성했습니다 /tmp
. 그런데 '라는 오류 메시지가 뜹니다
/bin/touch: Argument list too long
. 문제의 원인은 무엇입니까?
#!/bin/bash
dayNo=1
while test $dayNo -le 200
do
touch `find /tmp/`
sleep 86000
done
답변1
/tmp
파일이 너무 많습니다.적합하지 않음명령줄에 모든 이름을 한 번에 표시합니다(경로에 공백이 있으면 사용 중인 버전도 안전하지 않습니다).
좋은 소식은 find
다음과 같이 안전하고 정확하게 수행할 수 있다는 것입니다.
find /tmp -exec touch -c '{}' +
모든 파일은 이전과 마찬가지로 찾은 다음 touch
필요한 만큼 실행하여 매번 필요한 만큼의 파일을 실행합니다.
find
-exec
옵션일치하는 파일을 실행하고 경로를 바꾸는 명령을 수락합니다 {}
. +
즉, 여러 파일에 대해 한 번에 또는 각 파일에 대해 한 번씩 명령을 실행합니다 \;
.touch
의견에서 지적했듯이, -execdir touch -c '{}' \;
이는 엄격하게 더 안전하지만 단일 사용자 시스템에서는 약간 느리고 큰 이점이 없습니다. 먼저 각 하위 디렉터리로 전환한 다음 매번 해당 디렉터리의 파일에 대해서만 명령을 실행하여 특정 경쟁 조건을 방지합니다. 이 -execdir
옵션은 비표준 확장이지만 지원됩니다.암소 비슷한 일종의 영양,FreeBSD,오픈BSD,네트워크BSD, 그리고운영 체제 find
s; 다른 상용 Unices에는 일반적으로 이 기능이 없습니다. 무엇을 사용하고 있는지 잘 모르겠지만 해당되는 경우 위의 내용을 고려하세요.
답변2
쉘은 역따옴표 안의 표현식 결과를 해당 행으로 대체합니다. 그러나 시스템에는 명령 매개변수 목록의 길이에 대한 제한이 있습니다. 따라서 /tmp에 수천 개의 파일이 있으면 수천 개의 이름을 인수로 사용하여 명령을 생성하려고 시도합니다. 이것은 실패했습니다.
이 작업을 보다 쉽게 수행할 수 있는 방법에는 여러 가지가 있습니다. 검색 자체에서 명령을 실행할 수 있습니다. 대부분의 최신 버전에서는 분할하여 touch
각각 제한이 있는 여러 개별 명령을 실행할 수 있습니다.
find /tmp -exec touch {} +
답변3
질문에서 백틱 호출의 주요 문제점은 먼저 find 명령이 /tmp 아래의 모든 파일을 나열한 다음 해당 (거대한) 목록이 인수로 전달된다는 것입니다. touch
이는 단일 호출에 너무 많은 것입니다. 파일 이름에 공백, 줄 바꿈, 세미콜론, 앰퍼샌드, 파이프 문자 또는 유사한 문자가 포함되어 있는 경우에도 문제가 발생할 수 있습니다.
다음 구조를 사용하는 것이 더 좋습니다.
find /tmp -type f -exec touch -c '{}' +
이 find
명령은 재귀적으로 나열됩니다 /tmp
.
-type f
일반 파일만 선택하도록 find에 지시
이 -c
옵션을 사용하면 touch
Touch가 존재하지 않는 파일을 생성하는 것을 방지할 수 있습니다.
예제에서 몇 가지 논리를 생략한 것처럼 보이지만 200번만 수행하려는 경우 다음을 시도해 볼 수 있습니다.
#!/bin/bash 일수=1 $dayNo -le 200 테스트 시 하다 /tmp -type f -exec touch -c '{}' + 찾기 수면 86000 일수=$(식 1 + ${일수}) 완벽한