나는 많은 수의 파일(현재 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