수치 순서가있는 글롭


27

디렉토리 에이 pdf 파일 목록이 있습니다.

c0.pdf   c12.pdf  c15.pdf  c18.pdf  c20.pdf  c4.pdf  c7.pdf
c10.pdf  c13.pdf  c16.pdf  c19.pdf  c2.pdf   c5.pdf  c8.pdf
c11.pdf  c14.pdf  c17.pdf  c1.pdf   c3.pdf   c6.pdf  c9.pdf

고스트 스크립트를 사용하여 이것을 숫자 순서로 연결하고 싶습니다 (이와 유사 함).

gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf *.pdf

그러나 쉘 확장 순서는 숫자의 자연 순서가 아니라 알파벳 순서를 재현합니다.

$ for f in *.pdf; do echo $f; done
c0.pdf
c10.pdf
c11.pdf
c12.pdf
c13.pdf
c14.pdf
c15.pdf
c16.pdf
c17.pdf
c18.pdf
c19.pdf
c1.pdf
c20.pdf
c2.pdf
c3.pdf
c4.pdf
c5.pdf
c6.pdf
c7.pdf
c8.pdf
c9.pdf

확장에서 원하는 순서를 어떻게 달성 할 수 있습니까 (가능한 경우 0파일 이름의 숫자에 -padding을 수동으로 추가하지 않고 )?

사용할 제안을 찾았 ls | sort -V지만 특정 사용 사례에서 작동하도록 할 수 없었습니다.


당신은 할 수 알파벳 순서는 숫자 순서와 일치 있도록 그냥 모든 경우에 두 자리 숫자를 사용합니다. 어려운 일을하고 싶지 않다면
와일드 카드

1
최소한 3 자리 숫자! Y2K를 기억하십시오.
waltinator

답변:


12

환경에 따라 ls -vGNU coreutils와 함께 사용할 수 있습니다 . 예 :

gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
   -sOutputFile=out.pdf $(ls -v)

또는 최신 버전의 FreeBSD 또는 OpenBSD를 사용하는 경우 :

gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
   -sOutputFile=out.pdf $(ls | sort -V)

ls -v것입니다 natural sort of (version) numbers within text그래서 잘으로 사용할 수 있습니다 ...
Sundeep

@Sundeep : 사실, 이것은 GNU coreutils 전용 솔루션 인 것 같습니다.
Thor

예, GNU 고유의 것 같습니다 -pubs.opengroup.org/onlinepubs/9699919799
Sundeep

1
@Sundeep : POSIX에서도 -V기능을 sort지정하지 않았습니다. 그러나 FreeBSD와 OpenBSD가 모두 sort지원하는 것처럼 더 멀리 퍼져있는 것 같습니다 .
Thor

오, 자,이 세부 사항들을 추가하여 대답 할 수 있습니까? 비슷한 문제 (숫자 순서 글로브) 검색하고 보는 동안 나는이 대답을 가로 질러 온 ls은 자체 옵션 대신 :) 종류에 배관이 있다면 내가 체크 아웃 사용
Sundeep


12

문제의 파일이 모두 같은 접두사 (예 : 숫자 앞의 텍스트, c이 경우)를 사용하면

gs   … args…   c? .pdf c ??. pdf

c?.pdfc0.pdf c1.pdf…으로 확장합니다 c9.pdf.  ...로 c??.pdf확장됩니다 ( 해당되는 경우 최대 ). 경로 이름 확장 문자를 포함하는 각 명령 줄 단어는 변수 에 따라 정렬 된 (이름 정렬 된) 파일 이름 목록으로 확장되지만 인접한 와일드 카드 (글로브) 확장으로 인한 목록은 병합되지 않습니다. 그들은 단순히 연결되어 있습니다. (쉘 매뉴얼 페이지에 한 번 명시 적으로 언급했지만 지금은 찾을 수 없습니다.)c10.pdf c11.pdfc20.pdfc99.pdfLC_COLLATE

물론 파일이 올라갈 수 있으면를 c999.pdf사용해야합니다 c?.pdf c??.pdf c???.pdf. 물론, 숫자가 많으면 지루할 수 있습니다. 약간 축약 할 수 있습니다. 예를 들어 (최대) 5 자리의 경우을 사용할 수 있습니다 c?{,?{,?{,?{,?}}}}.pdf. 파일 이름 목록이 희소 한 경우 (예 : a c0.pdf와 a c12345.pdf가 있지만 반드시 사이에 모든 숫자가있는 것은 아님) nullglob옵션을 설정해야합니다 . 그렇지 않으면 (예를 들어) 두 자리 숫자의 파일이 없으면 c??.pdf프로그램에 리터럴 인수가 전달됩니다.

여러 접두사를 (예를 들어,이있는 경우 , 그리고 하나 또는 두 자리의 숫자), 당신은 분명, 무력 접근 방식을 사용할 수 있습니다 :a<number>.pdfb<number>.pdf c<number>.pdf

a?.pdf a??.pdf b?.pdf b??.pdf c?.pdf c??.pdf

또는 접습니다 {a,b,c}?{,?}.pdf.


1
그것의 스케치 사용의 주장을 넘어 때문에 이것은 최선의 대답이다 ls, stat다른 사람, 또는 아무것도; 요청에 따라 bash에서도 작동합니다.
카일

5

차이가 없다면 , 다음은 도움이 될 수 있습니다 (스케치 및 엣지 케이스 및 일반 성과 관련하여 강력하지는 않지만).

FILES="c0.pdf"
for i in $(seq 1 20); do FILES="${FILES} c${i}.pdf"; done
gs [...args...] $FILES

간격 이 있을 경우 약간의 [ -f c${i}.pdf ]검사가 추가 될 수 있습니다.

편집 은 또한 Bash를 사용하여 사용할 수있는 이 답변 을 참조하십시오.

gs [..args..] c{1..20}.pdf

타당한 이유가없는 한 쉘 변수 참조 (예 : "$FILES""$i") 를 인용하는 것이 일반적으로 좋습니다 . (괄호는 중요 할 수 있지만 반면에, 그들이 그렇게 예를 들어, 따옴표 등 중요하지 않은 "c$i.pdf"좋은 충분하다.) 같은 명령 , 파일의 공백으로 구분 된 목록을 포함,에 좋은 이유처럼 보일 수 있습니다 인용하지 않고 사용 하십시오 ( 해당 컨텍스트에서는 작동하지 않기 때문 입니다). ... (계속)gs  [ …args… ]  $FILES$FILES$FILES"$FILES"
G-남자 '는 분석 재개 모니카'말한다

(계속)… 그러나 bash / POSIX 쉘에서 변수를 인용하는 것을 잊어 버린 보안의 의미 , 특히 변수에 대한 나의 대답 은 bash에서 배열로 다중 단어 변수를 처리하는 방법에 대한 참고 사항입니다 (예 : FILES=("c0.pdf")FILES+=("c$i.pdf")). 또한 이 답변 은 내가 제안하는 기술을 사용합니다.
G-Man, 'Reinstate

1

단지 Thor의 대답을 인용하고 고치는 것만으로는 절대로 파싱하지 마십시오!

sort -V(POSIX 이외의 확장자로 정렬)을 사용할 수 있습니다 .

printf '%s\0' ./* | sort -zV \
    | xargs -0 gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH \
        -sDEVICE=pdfwrite -sOutputFile=out.pdf

(일부 명령의 경우 분명히 gs의 경우 그러한 명령 입니다. " " 대신 "./ " 가 필요 합니다. 하나가 작동하지 않으면 다른 것을 시도하십시오)


1
하지 구문 분석 LS 출력 할 수 있다 LS 표시 때문에 파일 이름을 바꿈으로 구분 된 개행 문자가 파일 이름에 유효로하지만, 여기 당신이 같은 일을하는 동안 stat파일 이름 시작 문제 (같은 여러 가지 다른 문제를하지만 추가 와 -, 너무 많은 파일이있는 경우, 문제 stat가 아닌 휴대용 명령 인). IFS를 조정하거나 글로브를 비활성화하지 않고 split + glob 연산자를 사용했기 때문에 공백이나 탭 또는 와일드 카드 문자가있는 파일 이름에 여전히 문제가 있습니다.
Stéphane Chazelas

GNU를 사용하려면 sort -V확실하게, 당신은 필요할 것 ${(z)"$(printf '%s\0' * | sort -zV)"}zsh(비록 zsh(n)이미 숫자 종류) 또는 readarray -td '' files < <(printf '%s\0' * | sort -zV)에서 bash4.4+.
Stéphane Chazelas

@ StéphaneChazelas 고맙습니다. 줄 바꿈이 문제가 될 수 있다는 것이 맞습니다. 그러나 이것이 ls를 구문 분석하지 않는 유일한 이유는 아닙니다. 그리고 네, 게으르고 추가하지 않았습니다. 그러나 나는 printf를 사용해야했을 것입니다 ... 나는 그것을 바꿀 것입니다.
피터

대한 ls(즉 -l없이) 혼자 그 무엇인가 다른 문제는 ? 그주의 --라는 파일에 대한 것없는 도움을 -.
Stéphane Chazelas

@ StéphaneChazelas 버전 사이에 다른 차이가 있습니다 ... 거기에 약간의 인쇄 "total 0"과 같은 최신 ls 버전은 원하지 않는 것들을 인용합니다. touch \"test\"; ls -1예를 들어 '"test"'내 ls에 표시 됩니다. 그것은 단순히 파싱되도록 ​​의도 된 것이 아니라 스크립팅 명령이 아닌 사용자 인터페이스입니다.
피터
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.