Sort filenames without leading zeros - bash

i would like to sort stereo imagefiles with the following pattern
img_i_j.ppm,
where i is the image counter and j is the id of the camera [0,1].
Currently, if i sort them using
ls -1 *.ppm | sort -n
the result looks like that:
img_0_0.ppm
img_0_1.ppm
img_10_0.ppm
img_10_1.ppm
img_1_0.ppm
img_11_0.ppm
img_11_1.ppm
img_1_1.ppm
img_12_0.ppm
But i need to have this output:
img_0_0.ppm
img_0_1.ppm
img_1_0.ppm
img_1_1.ppm
img_2_0.ppm
img_2_1.ppm
...
img_10_0.ppm
img_10_1.ppm
...
Is this achievable without adapting the filename?

As seen on the comments, use
sort -V
I initially posted it as a comment because this parameter is not always in the sort binary, so you have to use sort -k -n ... (for example like here).

ls (now?) has the -v option, which does what you want. From man ls:
-v natural sort of (version) numbers within text
This is simpler than piping to sort, and follows advice not to parse ls.
If you actually intend to parse the output, I imagine that you can mess with LC_COLLATE in bash. Alternatively, in zsh, you can just use the glob *(n) instead.

Related

Can you pipe into the bash strings command?

The strings command is a handy tool to extract printable strings from binary input files.
I've used it with files plenty.
But what if I wish to stream to it?
A use case is grepping a stream of data that may be binary for specific strings.
I tried
data-source | strings -- - | grep needle to see if the - had it treat stdin as a file type, but this doesn't work, strings just waits.
If you look at the help for strings:
Usage: strings [option(s)] [file(s)]
Display printable strings in [file(s)] (stdin by default)
You see that stdin is the default behavior if there are no arguments. By adding - the behavior seems to change, which is strange, but I was able to reproduce that result too.
So it seems the correct way to do what you want is:
data-source | strings | grep needle
In a comment, you asked why not strings datasource |grep -o needle ?
If you could arrange that command so datasource is a stream, it might work, but it's usually easier to arrange that using |.
For example, the below are roughly equivalent in zsh. You'd have to figure out a way to do it in your shell of choice if that's not zsh.
strings <(tail -f syslog) | grep msec
tail -f syslog | strings | grep msec

Sort files by number at end in bash/perl

I'm trying to sort a huge list of files into the following format:
file-55_357-0.csv
file-55_357-1.csv
file-55_357-2.csv
file-55_357-3.csv
...
Is there a simple way to do this in bash or perl? In other words, is there a way to write the perl script such that it goes through all of them in numerical order? For instance, when I create my #files, can I make sure the script goes through them all in this sorting -- how could I create a my #sorted array? I ask because I want to append all these files together vertically, and they need to be in the sorted order. Thanks so much!
You can use the sort command, which is neither part of bash nor part of perl.
With input data in input.txt:
file-55_357-123.csv
file-55_357-0.csv
file-55_357-21.csv
file-55_357-3.csv
From my shell, (any shell, not just bash) I can do the following:
$ sort -t- -nk3 input.txt
file-55_357-0.csv
file-55_357-3.csv
file-55_357-21.csv
file-55_357-123.csv
The -t option specifies a delimiter, -n says to compare numeric values (so that 21 comes after 3 rather than before) and -k 3 says to sort on the third field (per the delimiter).
use Sort::Key::Natural qw( natsort );
my #sorted = natsort #file_names;

Using the sort command in BASH in osx 10.9.4

I'm running the following command in a bash shell, and the result is not sorted. Am I missing something obvious here?
ls /bin /usr/bin | grep -v '/bin:$'| grep -v '^$' | sort > proglist
Instead of a sorted list, the results are:
2to3
2to3-
2to3-2.7
2to32.6
BuildStrings
CpMac
DeRez
GetFileInfo
MergePef
MvMac
RSA_SecurID_getpasswd
ResMerger
Rez
RezDet
RezWack
SetFile
SplitForks
UnRezWack
[
a2p
a2p5.12
a2p5.16
addftinfo
afconvert
afhash
afida
afinfo
afmtodit
afplay
agentxtrap
agvtool
alias
allmemory
applesingle
appletviewer
apply
apr-1-config
...
They're sorted in ASCII order. Numbers come before upper case letters, which come before lower case letters. Symbols and punctuation have various places in between and around them. You can try doing LC_COLLATE=en_US sort and see if it gives a better result.
It looks like the results ARE sorted, but they're also separated by file type...in descending order: numbers > uppercase > symbols > lowercase.
I don't have enough experience using the command line to tell you how to fix it, but that's something I would look into before trying anything drastic :)

sorting file names ascending where names have a dash in bash

I have a list of files in a folder.
The names are:
1-a
100-a
2-b
20-b
3-x
and I want to sort them like
1-a
2-b
3-x
20-b
100-a
The files are always a number, followed by a dash, followed by anything.
I tried a ls with a col and sort and it works, but I wanted to know if there's a simpler solution.
Forgot to mention: This is bash running on a Mac OS X.
Some ls implementations, GNU coreutils' ls is one of them, support the -v (natural sort of (version) numbers within text) option:
% ls -v
1-a 2-b 3-x 20-b 100-a
or:
% ls -v1
1-a
2-b
3-x
20-b
100-a
Use sort to define the fields.
sort -s -t- -k1,1n -k2 filenames.txt
The -t tells sort to treat - as the field separator in input items. -k1,1n instructs sort to first sort on the first field numerically; -k2 sorts using the remaining fields as the second key in cade the first fields are equal. -s keeps the sort stable (although you could omit it since the entire input string is being used in one field or another).
(Note: I'm assuming the file names do not contain newlines, so that something like ls > filenames.txt is guaranteed to produce a file with one name per line. You could also use ls | sort ... in that case.)

Sorting floats with exponents with 'sort -g' bash command

I have a file with floats with exponents and I want to sort them. AFAIK 'sort -g' is what I need. But it seems like it sorts floats throwing away all the exponents. So the output looks like this (which is not what I wanted):
$ cat file.txt | sort -g
8.387280091e-05
8.391373668e-05
8.461754562e-07
8.547354437e-05
8.831553093e-06
8.936111118e-05
8.959458896e-07
This brings me to two questions:
Why 'sort -g' doesn't work as I expect it to work?
How cat I sort my file with using bash commands?
The problem is that in some countries local settings can mess this up by using , as the decimal separator instead of . on a system level. Check by typing locale in terminal. There should be an entry
LC_NUMERIC=en_US.UTF-8
If the value is anything else, change it to the above by editing the locale file
sudo gedit /etc/default/locale
That's it. You can also temporarily use this value by doing
LC_ALL=C sort -g file.dat
LC_ALL=C is shorter to write in terminal, but putting it in the locale file might not be preferable as it could alter some other system-wide behavior such as maybe time format.
Here's a neat trick:
$ sort -te -k2,2n -k1,1n test.txt
8.461754562e-07
8.959458896e-07
8.831553093e-06
8.387280091e-05
8.391373668e-05
8.547354437e-05
8.936111118e-05
The -te divides your number into two fields by the e that separates out the mantissa from the exponent. the -k2,2 says to sort by exponent first, then the -k1,1 says to sort by your mantissa next.
Works with all versions of the sort command.
Your method is absolutely correct
cat file.txt | sort -g
If the above code is not working , then try this
sed 's/\./0000000000000/g' file.txt | sort -g | sed 's/0000000000000/\./g'
Convert '.' to '0000000000000' , sort and again subsitute with '.'. I chose '0000000000000' to replace so as to avoid mismatching of the number with the inputs.
You can manipulate the number by your own.

Resources