60k 이상의 파일에 enscript를 적용하는 방법은 무엇입니까?

60k 이상의 파일에 enscript를 적용하는 방법은 무엇입니까?

나는 많은 수의 파일(현재 Linux 커널에서 git에 의해 추적되는 모든 파일)에 Gnu enscript를 적용하고 싶습니다. 나는 단지 거기에 있습니다. 그러나 이러한 파일을 Python 스크립트와 같은 매개변수로 전달하기 위해 다양한 방법을 시도했지만 $(foo)매개변수를 너무 많이 지정했다고 합니다. 예를 들어 모든 파일의 이름을 files.txt한 줄에 하나씩 입력한 다음 호출 하면 enscript --color --toc -o out.ps $(<files.txt)오류가 인쇄됩니다. 동일한 매개변수 목록이 잘 작동합니다 echo. 이 문제를 해결하기 위해 enscript가 처리할 파일에서 읽는 기능을 추가하려고 시도했지만 수정하기 전에 enscript 소스 코드를 컴파일할 수 없었습니다. 내가 뭔가를 놓치고 있는 걸까요, 아니면 불가능한 걸까요?

답변1

문제는 하나의 명령줄(ARG_MAX, Linux의 경우 약 2MB)에 들어갈 수 없을 정도로 파일이 너무 많다는 것입니다.

이를 처리하는 방법에는 여러 가지가 있습니다. 가장 확실한 방법은 find's -exec옵션을 사용하는 것입니다. 이 옵션은 제한 내에 들어갈 만큼 많은 파일 이름 인수를 사용하여 명령의 여러 "배치"를 실행합니다. 예를 들어

find . -type f -exec sh -c 'enscript --color --toc -o "out.$(date +%s).ps" "$@"' sh {} +

물론 파일을 일치시키는 데 필요한 모든 검색 조건을 사용해야 합니다. 예를 들어 .git 디렉터리 자체를 제외하고 소스 코드 및 기타 텍스트 파일만 제외할 수도 있습니다.

out.ps파일 이름 에 현재 시간을 추가했습니다 . 이는 스크립트가 find파일 배치당 한 번 실행되고 두 번째 및 후속 배치가 첫 번째 배치의 출력을 덮어쓰는 것을 원하지 않기 때문입니다. sh -c ...각 입력 파일 배치에 대해 고유한 출력 파일 이름을 생성하는 더 좋고 더 예쁜 다른 방법이 있지만 이는 간단하고 작동하며 원리를 보여줍니다. 출력 파일 이름은 생성된 순서대로 정렬됩니다. 임시 파일에 카운터를 저장하는 것과 같은 변형은 독자의 연습 문제로 남겨집니다.

그런데 분명히 이것은 입력 파일의 각 배치에 대해 각각 자체 디렉토리가 있는 포스트스크립트 출력 파일을 생성합니다. 이는 모든 입력 파일과 디렉터리를 포함하는 하나의 출력 파일을 갖는 것과는 다릅니다. enscript표준 입력이나 파일에서 파일 이름 목록을 가져올 수 있는 방법이 없으므로 이것이 얻을 수 있는 가장 가까운 파일 이름 목록입니다 .


또 다른 옵션은 NUL로 구분된 파일에 파일 목록이 이미 있는 경우(파일 이름에 줄 바꿈이 포함되지 않을 것이 확실하다면 줄 바꿈으로 구분해도 괜찮습니다) 를 사용하는 것입니다 xargs.

NUL로 구분됨:

xargs -0r sh -c 'enscript --color --toc -o "out.$(date +%s).ps" "$@"' sh < files.list

개행 구분:

xargs -d '\n' -r sh -c 'enscript --color --toc -o "out.$(date +%s).ps" "$@"' sh < files.list

참고: -d-r옵션에는 GNU 버전의 xargs가 필요합니다. 일부 고대 및/또는 독점 버전의 xargs는 이를 지원하지 않지만 -0이러한 버전 중 하나를 접할 가능성은 거의 없습니다.


작동 원리:

명령줄에 맞는 만큼의 인수를 사용하여 지정된 명령을 find실행한 다음 모든 인수가 사용될 때까지 반복합니다.xargs

관련 정보