4

I want to join pdf files by pdfjoin/pdfunite/... in the numerical order discussed well in the thread answer linux command merge pdf files with numerical sort and Modified time order. If you use the solution in the thread, it puts the order in the numerical order and alphabetical order. This is problematic with the filenames such as where you see both have the same Modified time by minute accuracy but Visceral is earlier by second accuracy (File browser notes it and puts Visceral first in the Modified order.

Filename               Modified
-----                  ---
3.THE ABC.pdf          10:39 
3.Visceral abc..pdf    10:39

Complete filenames

1.Description abc.pdf
2.Gabcd.pdf
3.THE ABC.pdf
3.Visceral abc..pdf
4.description of abc.pdf
5.Chraa..pdf

Proposal #1 works in the numerical and alphabetical order but not in the numerical and modified order

# https://stackoverflow.com/a/23643544/54964
ls -v *.pdf | ...
    bash -c 'IFS=$'"'"'\n'"'"' read -d "" -ra x;pdfunite "${x[@]}" output.pdf'

Proposal #2 simplified case but does not deal whitespaces and other special characters in filenames

# https://stackoverflow.com/a/23643544/54964
pdfunite $(ls *.pdf | sort -n) output.pdf

There is nothing in the pdfunite --help about the ordering so I think it should be done by ls/sort/... The command sort does not have anything about modified in its man page.

Testing xhienne's answer

The order is not correct in the output where you see 2.jpg and 4.jpg are at the wrong order for some reason

masi@masi:~/Documents$ ls -tr /home/masi/Documents/[0-9]* | sort -t. -k1,1n -s
/home/masi/Documents/1.jpg
/home/masi/Documents/3.jpg
/home/masi/Documents/5.jpg
/home/masi/Documents/6.jpg
/home/masi/Documents/7.jpg
/home/masi/Documents/8.jpg
/home/masi/Documents/9.jpg
/home/masi/Documents/10.jpg
/home/masi/Documents/2.jpg
/home/masi/Documents/4.jpg

2nd iteration

export LC_ALL=C; ls -tr /home/masi/Documents/[0-9]* | sort -t. -k1,1n -s

Output

/home/masi/Documents/1.jpg
/home/masi/Documents/3.jpg
/home/masi/Documents/5.jpg
/home/masi/Documents/6.jpg
/home/masi/Documents/7.jpg
/home/masi/Documents/8.jpg
/home/masi/Documents/9.jpg
/home/masi/Documents/10.jpg
/home/masi/Documents/2.jpg
/home/masi/Documents/4.jpg

OS: Debian 8.5

  • Is is not clear to me whether you want an alphabetical/numerical sort, or a modification-time sort. – xhienne Dec 23 '16 at 11:13
  • @xhienne I want AND of them. First numerical sort by the numbers in the prefix and then by modification-time sort. – Léo Léopold Hertz 준영 Dec 23 '16 at 11:28
5

You could do that with zsh:

zmodload zsh/stat

prefixmtime () {
sortstring=${(l:6::0:)${REPLY%%.*}}$(zstat -F '%s' +mtime -- $REPLY)
REPLY=${sortstring}
}

print -rl -- *(o+prefixmtime)

Replace print -rl with your command if you're happy with the result


How it works:
The globs will sort here (via o+function) based on what the function prefixmtime returns, that is sortstring which is a string obtained by concatenating the numerical prefix of each file name ${REPLY%%.*} left-padded with zeros (l:6::0:) (assuming prefixes are up to 6-chars long) and the mtime in seconds (obtained via zstat module). It may be easier to understand how it works if you run:

{ for f (*)
printf '%s %s\n' ${(l:6::0:)${f%%.*}}$(zstat -F '%s' +mtime -- $f) $f
} | sort -k1,1n

Note that the above assumes you're in the same directory with your files, otherwise you'll have to define the sort string in that function as

sortstring=${(l:6::0:)${${REPLY##*/}%%.*}}$(zstat -F '%s' +mtime -- $REPLY)

and then you can use directory paths e.g.

print -rl some/place/else/*(o+prefixmtime)
  • How did you figured out sortstring? What is *(o+prefixtime) in Zsh? - - How is zsh/stat related to R? – Léo Léopold Hertz 준영 Dec 23 '16 at 16:30
  • 1
    @Masi - o+function is a glob qualifier, see link in my post. I'm having a hard time understanding your other questions. – don_crissti Dec 23 '16 at 18:09
4
find /home/masi/Documents -maxdepth 1 -type f -name '[0-9]*' -printf "%T+ %f\n" | sort -k2n -k1,1| cut -d ' ' -f 2- | xargs -i echo pdfunite /home/masi/Documents/{} output.pdf

This will not handle new lines in filenames.

You can toggle reversing the sort orders by changing -k1,1 to -k1,1r which will reverse the time sort and -k2nr will reverse the filename sort.

2

The solution is to first sort by modification time, then sort only on the first numerical field (assuming the fields are separated by '.') while disabling the last resort comparison (a.k.a. stable sort).

ls -tr [0-9]* | sort -t. -k1,1n -s

[update]

Since you appear to have white-spaces in your filenames, you must use xargs to execute pdfunite:

ls -tr [0-9]* | ( sort -t. -k1,1n -s; echo output.pdf ) | xargs pdfunite
  • How to do expand this to cover whitespaces in filenames? See Proposal #1. – Léo Léopold Hertz 준영 Dec 23 '16 at 11:38
  • @Masi Use xargs. I have updated my answer with an example – xhienne Dec 23 '16 at 11:59
  • Please, see the body. The first command has something wrong in it. – Léo Léopold Hertz 준영 Dec 23 '16 at 12:30
  • @Masi You might have a bizarre locale problem. Can you try export LC_ALL=C before my command? – xhienne Dec 23 '16 at 12:39
  • Please, see the body for the output. - - So it does not help. My system is default 8.5 Debian. – Léo Léopold Hertz 준영 Dec 23 '16 at 12:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.