Glob with Numerical Order

I have this list of pdf files in a directory:

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

I want to concatenate these using ghostscript in numerical order (similar to this):

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

But the shell expansion order does not reproduce the natural order of the numbers but the alphabetical order:

$ 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

How can I achieve the desired order in the expansion (if possible without manually adding 0-padding to the numbers in the file names)?

I’ve found suggestions to use ls | sort -V, but I couldn’t get it to work for my specific use case.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Once more, zsh’s glob qualifiers come to the rescue.

echo *.pdf(n)

Method 2

Depending on your environment you can use ls -v with GNU coreutils, e.g.:

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

Or if you are on recent versions of FreeBSD or OpenBSD:

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

Method 3

If all the files in question have the same prefix
(i.e., the text before the number; c in this case), you can use

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

c?.pdf expands to c0.pdf c1.pdfc9.pdf
c??.pdf expands to c10.pdf c11.pdfc20.pdf
(and up to c99.pdf, as applicable). 
While each command-line word containing pathname expansion character(s)
is expanded to a list of filenames sorted (collated) in accordance
with the LC_COLLATE variable,
the lists resulting from the expansion of adjacent wildcards (globs)
are not merged; they are simply concatenated. 
(I seem to recall that the shell man page once stated this explicitly,
but I can’t find it now.)

Of course if the files can go up to c999.pdf,
you should use c?.pdf c??.pdf c???.pdf
Admittedly, this can get tedious if you have a lot of digits. 
You can abbreviate it a little; for example, for (up to) five digits,
you can use c?{,?{,?{,?{,?}}}}.pdf
If your list of filenames is sparse
(e.g., there’s a c0.pdf and a c12345.pdf,
but not necessarily every number in between),
you should probably set the nullglob option. 
Otherwise, if (for example) you have no files with two-digit numbers,
you would get a literal c??.pdf argument passed to your program.

If you have multiple prefixes
(e.g., a<number>.pdf,
b<number>.pdf ,
and c<number>.pdf ,
with numbers of one or two digits),
you can use the obvious, brute force approach:

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

or collapse it to {a,b,c}?{,?}.pdf.

Method 4

If there are no gaps, the following could prove helpful (albeit sketchy and not robust concerning edge-cases and generality) — just to get an idea:

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

If there may be gaps, some [ -f c${i}.pdf ] check could be added.

Edit also see this answer, according to which you could (using Bash) use

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

Method 5

Just quoting and fixing Thor’s answer… NEVER parse ls!

You can use sort -V (a non-POSIX extension to sort):

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

(for some commands, apparently for gs is such a command, you need “./” instead of ““… if one doesn’t work, try the other)


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x