이 문제를 개선하는 방법은 매개변수가 너무 낮거나 for 루프가 너무 느린 경우입니다.

이 문제를 개선하는 방법은 매개변수가 너무 낮거나 for 루프가 너무 느린 경우입니다.

내가 시도할 때

du -sh $(sed -ne '/\.[hc]$/p' ../all-file)

그것은 말한다 $ bash: /usr/bin/du: Argument list too long

그럼 난 노력해

for i in $(sed -ne '/\.[hc]$/p' ../all-file); do du "$i"; done|vim -

그러나 완료하는 데 오랜 시간이 걸립니다.

소란을 피우지 않고 어떻게 작업 속도를 높일 수 있나요?

답변1

제공된 의견을 토대로 이 사실을 파악하셨나요?

sed -ne '/\.[hc]$/p' ../all-file | xargs du -sh

grep을 사용하지 않는 이유는 무엇입니까? 적어도 두 배는 빠릅니다.

grep '\.[hc]$' ../all-file | xargs du -sh

답변2

GNU 구현을 사용하면 du다음을 수행할 수 있습니다.

<../all-file LC_ALL=C grep '\.[hc]$' |
  tr '\n' '\0' |
  du -sh --files0-from=-

GNU를 통해 구현됨 xargs:

<../all-file LC_ALL=C grep '\.[hc]$' |
  xargs -rd '\n' du -sh --

또는 대부분의 BSD에서와 같이 GNU 를 xargs복사하는 다른 구현을 사용하십시오.-r-0-d

<../all-file LC_ALL=C grep '\.[hc]$' |
  tr '\n' '\0' |
  xargs -r0 du -sh --

그러나 하드 링크의 디스크 사용량은 한 번만 보고되므로 du목록을 이와 같이 일괄 처리로 분할하면 xargs결과가 달라질 수 있습니다 . 이 -c옵션을 사용하여 마지막에 누적된 결과를 얻으려면 이 --files0-from방법도 사용해야 합니다.

예:

$ seq 100000 > a.c
$ ln a.c b.c
$ du -shc a.c b.c
651K    a.c
651K    total

b.c이것이 실제로 와 관련되어 있으므로 이것이 어떻게 보고되지 않는지 확인하십시오 a.c. 두 파일의 누적 디스크 사용량은 651K입니다.

$ du -shc a.c; du -shc  b.c
651K    a.c
651K    total
651K    b.c
651K    total

총 651K의 파일 2개를 얻게 되는데, 이는 ac와 bc가 동일한 파일이라는 사실을 숨깁니다.

반면에 하드 링크 처리를 비활성화하고 GNU 구현을 통해 각 파일의 디스크 사용량을 개별적으로 보고하려면 / 옵션을 du사용할 수 있습니다 . 디스크 사용량보다는 파일 크기에 관심이 있는 경우에도 이 옵션을 참조하세요.-l--count-links--apparent-size

최신 버전의 Linux에서는 리소스 제한을 늘려 매개변수 + 환경 크기 제한을 늘릴 수 있습니다 stacksize.

예를 들어 다음을 사용하면 ulimit -s unlimited대부분의 쉘( limit stacksize unlimitedzsh에서도 하위 프로세스에서만 작동함)에서 제한을 무시하고 목록 분해를 피할 수 있습니다.

$ /bin/true {1..150000}
zsh: argument list too long: /bin/true
(127)$ limit stacksize unlimited
$ /bin/true {1..150000}
$ /bin/true {1..250000}
$ /bin/true {1..350000}
$ /bin/true {1..500000}
zsh: argument list too long: /bin/true

그런 다음 분할+glob을 사용할 수 있지만 항상 그렇듯이 구분 기호를 줄 바꿈( IFS=$'\n')으로 수정하고 아마도 원하지 않는 와일드카드( )를 비활성화 하도록 조정해야 합니다 set -o noglob.

(
  ulimit -s unlimited
  IFS=$'\n'
  set -o noglob
  du -sh -- $(<../all-file LC_ALL=C grep '\.[hc]$')
)

../all-file이 패턴과 일치하는 줄이 없으면 du인수 없이 실행하게 되며 기본적으로 현재 작업 디렉터리의 디스크 사용량을 가져옵니다( -r선택적으로 xargs이러한 경우를 처리할 수 있음).

추가 참고사항:

  • sed -ne /re/pis ( s 에서 파생되었지만 약어 grep입니다 ).grepedg/re/p
  • 파일 경로는 NUL이 아닌 바이트로 구성될 수 있으며 임의의 목록을 나타낼 수 있으려면 NUL로 구분하는 것이 확실한 선택이므로 --files0-fromNUL로 구분된 목록이 필요합니다. 이는 개행으로 구분된 all-file파일이 임의의 파일 경로를 나열할 수 없음을 의미합니다. 이는 또한 파일 경로가 텍스트로 구성될 필요가 없기 때문에 텍스트 유틸리티를 사용하여 파일 경로를 처리하는 것이 모든 바이트가 문자인 C와 같은 로케일을 제외하고 작동이 보장되지 않는다는 것을 의미합니다. 를 사용하면 LC_ALL=C바이트를 문자로 디코딩하는 것을 방지하므로 성능이 향상될 수도 있습니다.
  • $(...)Bash에서 인용되지 않은 버전은 Split+Glob입니다. 파일 경로에 전역 문자나 $IFS변수의 문자가 포함되어 있지 않다는 것을 알고 있는 경우에만 해당 파일 목록을 사용하여 파일 목록을 분할할 수 있습니다.
  • / 가 xargs없는 경우 분할은 공백 또는 개행 문자에서 수행되며 작은따옴표/큰따옴표 및 백슬래시는 이스케이프 연산자로 해석됩니다. 즉, 보이는 것처럼 개행으로 구분된 임의의 파일 경로 목록을 처리할 수 없습니다 .-0-dall-file
  • 변수, 사전에 알려지지 않은 인수 목록을 명령에 전달할 때 첫 번째(또는 GNU 구현이 있는 모든 인수) 인수가 다음 으로 --끝나도록 하기 위해 옵션 앞에 이 옵션의 끝을 표시 해야 합니다. 명령)은 옵션으로 간주되지 않습니다.-+

관련 정보