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.