2

I want to use find and sort the response. I assumed that a simple pipe find ... | sort would do it, but the sorting behaviour is weird. For simplicity a simple text file:

asdf/2/22
asdf/2/01
asdf/20/0
asdf/20/1

My expected result would be

asdf/2/01
asdf/2/22
asdf/20/0
asdf/20/1

or

asdf/20/0
asdf/20/1
asdf/2/01
asdf/2/22

It doesn't matter as I only want the directories to appear in groups.

Here are my attempts:

[root@linux6 ~]# cat sort_test | sort
asdf/20/0
asdf/2/01
asdf/20/1
asdf/2/22
[root@linux6 ~]# cat sort_test | sort -d
asdf/20/0
asdf/2/01
asdf/20/1
asdf/2/22
[root@linux6 ~]# cat sort_test | tr "/" "X" | sort
asdfX20X0
asdfX20X1
asdfX2X01
asdfX2X22
[root@linux6 ~]# cat sort_test | tr "/" "_" | sort
asdf_20_0
asdf_2_01
asdf_20_1
asdf_2_22
[root@linux6 ~]#

Note that it only works with "X". Any non-alphanumeric character seems to break the output. I also tried the -s, -t '/' options with no change in the output.

sort seems to remove the non-alphanumeric characters first and then sort the line even though I didn't mention -d. There is no alias for sort.

[root@linux6 ~]# which sort
/usr/bin/sort
[root@linux6 ~]# uname -a
Linux i-epg-appl1 3.10.0-229.14.1.el7.x86_64 #1 SMP Tue Sep 15 15:05:51 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
[root@linux6 ~]# sort --version
sort (GNU coreutils) 8.22
3
  • 3
    Switch collation to C e.g. LC_COLLATE=C sort infile Mar 17, 2016 at 11:27
  • Or also try LANG to be set to C (or en_US.UTF-8) Mar 17, 2016 at 11:54
  • 1
    @don_crissti You are right, it wasn't set on my machine. If you want some reputation make that an answer :). BTW, LANG is set and apparently didn't help here.
    – sjngm
    Mar 17, 2016 at 12:17

2 Answers 2

2

In first instance, the / will be ignored in your locale for sorting (you'll notice that all but the last weight in the collection specification for / is IGNORE on a GNU system for most locales (<U002F> IGNORE;IGNORE;IGNORE;<U002F> # 45 / in /usr/share/i18n/locales/iso14651_t1_common on my Debian system)), so sorting asdf/20/0 against asdf/2/01 is like sorting asdf200 against asdf201, as if you had used -d.

You could change the locale to C where the sorting is only based on byte value (and / happens to sort before digits) so asdf/2/01 would sort before asdf/20/0 as / sorts before 0, but you'd still have problem with asdf/2 against asdf/10 for instance.

Here, you could use the GNU-specific -g/--general-numeric-sort option, or you could do:

sort -nt/ -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 -k6,6 -k7,7 -k8,8 -k9,9

To consider each directory component as a number (that will sort 2_ before

With zsh, you can do:

printf '%s\n' **/*(Dn)

to do a recursive glob numerically sorted.

0

So just to wrap up this question the answer is to set LC_COLLATE as @don_crissti mentioned in the comment:

$ LC_COLLATE=C sort infile

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .