디렉토리에 있는 각 PDF 문서의 파일 이름과 페이지 번호를 반환합니다.

디렉토리에 있는 각 PDF 문서의 파일 이름과 페이지 번호를 반환합니다.

컨텍스트: Catalina MacOS: .pdf 파일 세트가 포함된 디렉터리입니다. 일부 파일 이름에 공백이 포함되어 있습니다(xargs.txt에 문제가 있음)

명령줄에서: 목표는 각 .pdf 파일의 파일 이름과 페이지 번호를 반환하는 것입니다.

이 코드 조각은 파이프로 연결할 수 있는 파일 이름 목록을 반환합니다.매개변수:

find . -type f -name  '*.pdf'

이 조각은 페이지 수를 반환합니다.

pdfinfo foo.pdf | grep Pages | awk '{print $2}' 


pdftk foo.pdf dump_data | grep Pages | awk '{print $2}'

xargs와 함께 코드 조각을 사용하여 파일 이름에 공백이 포함될 수 있는 .pdf 파일만 처리하려면 어떻게 해야 합니까?

실패:

 find . -name '*.pdf' | xargs pdfinfo | 

코드 조각은 파일 이름을 인쇄하고(공백이 있는 이름은 처리할 수 없지만) 파일 이름과 같은 줄에 페이지 번호를 인쇄하지 않습니다.

find . -name '*.pdf' | xargs -I % sh -c 'echo %;  pdfinfo % | grep Pages'

답변1

일부 파일 이름에 공백이 포함되어 있습니다(xargs.txt에 문제가 있음)

-print0options find-0options 을 사용하면 됩니다 xargs. 그들은 맨 페이지 상단에 이것을 광고해야 합니다!

find -iname '*.pdf' -print0 | xargs -0 ...

그게 다야. 이 옵션은 find발견된 파일 이름을 개행 대신 0바이트로 구분하도록 지시합니다. 공백, 개행, 콜론 등과 달리 0바이트는아니요파일 이름에는 허용되므로 파일 이름을 구분하는 안전한 방법입니다. 구분 기호로 0바이트를 예상하도록 -0지시합니다 .xargs

그러나 이것은 OS X이고 쉘은 아마도 잘 작동할 것이므로 find전혀 필요하지 않습니다.

#!/usr/bin/zsh -

for pdffile in **/*.pdf(N-.) ; do
   print -r -- "${pdffile}" # This is already problematic again. Your file names
                            # might contain newlines, spaces etc, so no easy way
                            # to tell where file name ends and page count starts
   pdfinfo -- "${pdffile}" | grep Pages | awk '{print $2}'
done

참고하세요더블"사용하려는 따옴표 : 래핑된 문자열이 변수 확장을 거치지 않아 문자열이 호출 프로그램에 있는 그대로(달러 기호 및 변수 이름 포함) 전달되기 '때문에 코드가 작동하지 않습니다 . 이는 전달해야 하기 때문에 '원하는 매개변수 이지만 실제로 변수 내용을 확장하려는 위치는 아닙니다.awk$

블러 플로팅에 대한 대답은 정확합니다. grep을 awk호출에 흡수할 수 있습니다. 또한 정규 표현식이 최대한 정확한지 확인해야 합니다.

또한 0으로 구분된 출력을 생성하여 "파일 이름에 공백, 줄 바꿈 및 숫자가 포함될 수 있으므로 출력에서 ​​파일 이름이 시작하고 끝나는 위치를 알 수 없습니다" 문제를 해결할 수도 있습니다.

#!/usr/bin/zsh

for pdffile in **/*.pdf(N-.) ; do
   pages=$(pdfinfo -- "${pdffile}" | awk '/^Pages:/{print $2}')
   printf '%s\0\%d\0' "${pdffile}" "${pages}"
done

(PDF 파일에는 여전히 문제가 있을 수 있습니다.창조자또는생산자포함 <newline>Pages:하지만 최소한 위의 엄격한 정규식을 사용하여 위험을 최소화했습니다.

답변2

find명령 을 사용 -exec하여 실행 pdfinfo한 후 결과를 파이프하면 중간 단계 awk없이 자체적으로 패턴 일치를 수행할 수 있습니다 .grep

find . -type f -name '*.pdf' -exec pdfinfo '{}' \; | awk '/Pages/ {print $2}'

물론 이것은 페이지 수만 제공합니다. 이제 각 파일에 대해 필요한 것을 알 수 있습니다.파일 이름 그리고총 페이지. 나는 xargs그것이 여기서 도움이 될 것이라고 생각하지 않지만 while루프가 그 일을 할 것입니다:

#!/bin/sh
find . -type f -name '*.pdf' | while read -r f; do
    p=$(pdfinfo "$f" | awk '/Pages/ {print $2}')
    printf '%s\n' "$f $p"
done

답변3

디렉터리 트리를 순회할 필요가 없는 경우 이 for루프는 다음을 수행할 수 있습니다.

for FN in *pdf; do pdfinfo "$FN" | awk '/^Pages/ {print ARGV[2], $2; exit}' - "$FN"; done

답변4

그리고 exiftool:

exiftool -r -ext pdf -q -p '$PageCount $Directory/$Filename' .

-r(재귀의 경우) 와 함께 사용 -ext pdf하면 비슷한 작업을 수행합니다 find . -name '*.pdf'.

프리젠테이션용으로 좋습니다.

쉘 루프와 같이 사후 처리 가능한 출력의 경우 NUL로 구분된 출력 형식을 사용하는 것이 좋습니다.

exiftool -r -ext pdf -q -if 'print "$PageCount/$Directory/$Filename\0";0' . |
  while IFS=/ read -rd '' page file; do
    something with "$page" and "$file"
  done

( zsh또는 가정 bash -O lastpipe)

또는 json, xml 또는 php1과 같이 지원하는 일부 직렬화 형식:

$ exiftool -r -ext pdf -q -j -PageCount .
[{
  "SourceFile": "./a.pdf",
  "PageCount": 4
},
{
  "SourceFile": "./a\nb.pdf",
  "PageCount": 4
}]
$ exiftool -r -ext pdf -q -X -PageCount .
<?xml version='1.0' encoding='UTF-8'?>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>

<rdf:Description rdf:about='./a.pdf'
  xmlns:et='http://ns.exiftool.ca/1.0/' et:toolkit='Image::ExifTool 11.88'
  xmlns:PDF='http://ns.exiftool.ca/PDF/PDF/1.0/'>
 <PDF:PageCount>4</PDF:PageCount>
</rdf:Description>

<rdf:Description rdf:about='./a
b.pdf'
  xmlns:et='http://ns.exiftool.ca/1.0/' et:toolkit='Image::ExifTool 11.88'
  xmlns:PDF='http://ns.exiftool.ca/PDF/PDF/1.0/'>
 <PDF:PageCount>4</PDF:PageCount>
</rdf:Description>
</rdf:RDF>
exiftool -r -ext pdf -q -php -PageCount .
Array(Array(
  "SourceFile" => "./a.pdf",
  "PageCount" => 4
),
Array(
  "SourceFile" => "./a\nb.pdf",
  "PageCount" => 4
));

(여기서는 개행 문자가 포함된 파일 이름을 예로 사용합니다.)


그러나 JSON 및 XML은 UTF-8로 적절하게 인코딩된 텍스트로 구성된 파일 이름에서만 작동하며 이는 이러한 형식의 제한 사항입니다.

관련 정보