ls에 대한 인수 목록이 너무 깁니다.


48

ls *.txt | wc -l많은 파일이 포함 된 디렉토리를 시도 할 때 다음 오류가 발생 합니다.

-bash: /bin/ls: Argument list too long

이 "인수 목록"의 임계 값은 배포 또는 컴퓨터 사양에 따라 달라 집니까? 일반적으로 큰 결과의 결과를 다른 명령 ( wc -l예 :)으로 파이프 하므로 터미널의 한계에 관심이 없습니다.


6
그것은 파싱 ls의 출력 으로 계산되며 , 이는 나쁜 생각이므로 피하는 것이 좋습니다. 계산은 디렉토리의 파일 수를 계산하는 가장 좋은 방법무엇입니까? 를 참조하십시오 . 까다로운 해결 방법은 for 루프가 "인수가 너무 길다"오류를 발생시키지 않는 이유를 참조하십시오 . .
manatwork

@manatwork 예, 그 질문들도 보았습니다. 더 일반적인 방식으로 명령의 긴 출력을 사용하거나 리디렉션하는 더 좋은 방법이 궁금합니다.

getconf ARG_MAX를 사용하여 대부분의 유닉스 기반 시스템에서 한계를 얻을 수 있습니다
Prasanth

답변:


49

귀하의 오류 메시지 인수 목록이 너무 오래 로부터 오는 *ls *.txt.

이 제한은 바이너리 프로그램과 커널 모두에 안전합니다. 당신은에서 볼 수있는 페이지 가 사용 계산 어떻게 그것에 대한 자세한 내용은합니다.

파이프 크기에는 이러한 제한이 없습니다. 따라서이 명령을 간단히 실행할 수 있습니다.

find -type f -name '*.txt'  | wc -l

주의 : 현대 리눅스에서 (줄 바꿈 등) 파일 이름에 이상한 문자가 같은 도구로 이스케이프됩니다 ls또는 find,하지만 여전히에서 표시 * . 오래된 유닉스에 있다면이 명령이 필요합니다

find -type f -name '*.txt' -exec echo \;  | wc -l

NB2 : 이름에 줄 바꿈이있는 파일을 만드는 방법이 궁금합니다. 트릭을 알고 나면 그렇게 어렵지 않습니다.

touch "hello
world"

1
줄 바꿈 파일 이름이있는 경우 작동하도록 약간 수정했습니다. -maxdepth 1하위 디렉토리에서 파일을 계산하지 않으려는 경우 추가 할 수도 있습니다 .
Shawn J. Goff

필요하지 않습니다 -exec echo \;.
Mikel

@ ShawnJ.Goff 테스트했습니다. 현재 버전의 GNU find에는`echo`가 필요 없습니다
Coren

@Coren @Mikel – 모든 사람이 GNU를 가지고있는 것은 아닙니다 find. find내가 어떤 BSD 기반 시스템을 추측 할 OS에 X와 비지 박스 기반 시스템에서, 그리고 카운트와 그 안에 줄 바꿈, 것 엉망와 파일 이름을 보여줍니다.
Shawn J. Goff

응? wc -l줄 바꿈을 세고 있습니다. 그래서 우리 는 줄 바꿈을 원합니다 .
Mikel

11

주로 Linux 커널 버전에 따라 다릅니다.

다음을 실행하여 시스템의 한계를 볼 수 있어야합니다

getconf ARG_MAX

이것은 쉘에 의해 확장 된 후 명령 행이 가질 수있는 최대 바이트 수를 알려줍니다.

Linux <2.6.23에서 한계는 일반적으로 128KB입니다.

Linux> = 2.6.25에서 제한은 128KB 또는 스택 크기의 1/4 (참조 ulimit -s) 중 더 큰 값입니다.

자세한 내용은 execve (2) 매뉴얼 페이지참조 하십시오.


불행히도, 배관 ls *.txt이 문제를 해결하지 못할 것입니다. 한계는 쉘이 아닌 운영 체제에 있기 때문입니다.

셸이을 확장 한 *.txt다음

exec("ls", "a.txt", "b.txt", ...)

일치 *.txt하는 파일이 너무 많아 128KB 제한을 초과합니다.

당신은 뭔가를해야합니다

find . -maxdepth 1 -name "*.txt" | wc -l

대신에.

(그리고 개행을 포함하는 파일 이름에 대한 아래의 Shawn J. Goff의 의견을 참조하십시오.)


답변을 올리지 못해 죄송합니다. 더 많은 평판이 필요합니다. :( 감사합니다 !!

마지막 줄 .-maxdepth 1의미 와 의미 를 설명해 주 시겠습니까? 감사! : D
Guilherme Salomé 2016 년

2
@ GuilhermeSalomé .는 현재 디렉토리를 -maxdepth 1의미하며 하위 디렉토리를 찾지 않습니다. 이것은와 동일한 파일을 일치시키기위한 것 *.txt입니다.
Mikel

9

다른 해결 방법 :

ls | grep -c '\.txt$'

생성 (또는 생성 시도) ls보다 더 많은 출력을 생성 하더라도 ls *.txt"인수가 너무 오래"문제가 발생하지 않습니다 . 인수를 전달 하지 않기 때문 ls입니다. 참고 grep파일 일치 패턴보다는 정규 표현식을합니다.

다음을 사용할 수 있습니다.

ls -U | grep -c '\.txt$'

(버전 ls이이 옵션 을 지원 한다고 가정 ). 이렇게 ls하면 출력을 정렬하지 않아도되므로 시간과 메모리를 모두 절약 할 수 있습니다.이 경우 파일을 계산하기 때문에 순서가 중요하지 않습니다. 출력 정렬에 소비 된 리소스는 일반적으로 중요하지 않지만이 경우 이미 많은 *.txt파일 이 있다는 것을 알고 있습니다 .

그리고 단일 디렉토리에 너무 많은 파일이 없도록 파일을 재구성하는 것을 고려해야합니다. 이것은 가능할 수도 있고 아닐 수도 있습니다.


1

MAX_ARG_PAGES는 커널 매개 변수 인 것으로 보입니다. findand를 사용하면 xargs이 한도를 해결하기위한 일반적인 조합이지만 작동하지 않을 것입니다 wc.

find . -name \*\.txt파일 의 출력을 파이핑하고 해당 파일의 행을 계산하면 해결 방법으로 사용됩니다.


ls의 출력으로 무엇이든 할 수 있지만 이것을 해결할 수는 없습니다. * .txt 와일드 카드가 제한을 넘어 확장되면 ls출력을 시작 하고 생성 하기 전에도 실패 합니다.
manatwork

사실, 나는 대답을 업데이트했다.
Bram

보다 나은. 그러나이를 대체 하려면 서브 디렉토리를 재귀 적으로 스캔하지 않도록 ls지정해야합니다 -maxdepth 1.
manatwork

답변을 올리지 못해 죄송합니다. 더 많은 평판이 필요합니다. :(

0

이것은 더러울 수 있지만 내 요구와 역량 내에서 작동합니다. 나는 그것이 매우 빨리 수행한다고 생각하지 않지만 그것은 내 하루를 시작할 수있게했습니다.

ls | grep jpg | <something>

90,000 개의 긴 jpg 목록을 가져 와서 avconv로 파이핑하여 timelapse를 생성했습니다.

이전에 ls * .jpg를 사용했습니다. | 이 문제가 발생하기 전에 avconv.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.