0

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!

JDY
  • 167
  • 2
  • 10
  • Your example already appears to be sorted. Do you want it in some other order than it already is? Please show us your input data, your intended output, your attempt to get there, and what's going wrong with that attempt. – ghoti Aug 19 '15 at 16:08
  • I apologize. The example is what I want. I have them in the order of file-55_357-122.csv, file-55_357-2.csv, ... I was looking this up on some other forums, and couldn't get sort command to work correctly. – JDY Aug 19 '15 at 16:19

2 Answers2

2

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).

ghoti
  • 45,319
  • 8
  • 65
  • 104
  • I don't have all the list of files in a .txt file -- in essence, I was wondering if I can sort all the files directly in the directory. – JDY Aug 19 '15 at 16:34
  • The directory is just a list, not implicitly sorted. The best way to sort will be determined by what you want to *do* with the resultant list. The reason for this is explained pretty clearly (and with some humour) in the [XyProblem](http://mywiki.wooledge.org/XyProblem) page on [greycat's BASH FAQ](http://mywiki.wooledge.org/BashFAQ). – ghoti Aug 19 '15 at 16:46
  • Oh, and if you put the file list into a bash array with something like `a=(*)`, you may be able to sort it with a variation of the answer to [this question](http://stackoverflow.com/a/30576368/1072112). – ghoti Aug 19 '15 at 16:50
  • I just need to have them sorted numerically so that I can run a script through them and append them all. I think I will try sorting it in perl first, unless there is a better solution. I will edit my question. – JDY Aug 19 '15 at 17:24
  • I don't understand "append them all". You want to [append text to every file](http://stackoverflow.com/q/10865947/1072112)? Or just concatenate the files together in natural order? If the latter, `ls | sort -t- -nk3 | xargs -n 1 cat > output.txt` might be sufficient, if you don't have special characters (including spaces) in your filenames. – ghoti Aug 19 '15 at 20:35
  • The latter. I'd like to concatenate the files together in the natural order. Thank you for your help -- it works nicely, but could you explain to me `xargs -n 1 cat`? I'm trying to learn for future reference. Also, if I wanted to concatenate all files ending in .csv, would I just do `... xargs -n 1 cat *.csv > output.txt`? Thanks! – JDY Aug 19 '15 at 20:42
  • So... The `xargs` command takes standard input and turns it into command line options. Normally, `echo one two | xargs echo` would run `echo one two`. With the `-n 1` option, you tell xargs to process one option at a time, so `echo one two | xargs -n 1 echo` would run `echo one` and then `echo two`. Try it for yourself! In your case, we may have more files than will fit on one command line, so we'll `cat` each of them separately, but aggregate the output with the redirect. – ghoti Aug 20 '15 at 10:52
  • And no, that's not now you would capture just the `*.csv` files. Your source file list is provided by the output of the `ls` command. Again, if you have more files than will fit on one command line, `ls *.csv` won't work, and you may need to use the `find` command to process things. In that case, `find /path -name "*.csv" -exec cat {} \; > output.txt` would likely be the way to go. Though you might also need to use the `-maxdepth` option depending on what's in your directories. – ghoti Aug 20 '15 at 10:54
1
use Sort::Key::Natural qw( natsort );

my @sorted = natsort @file_names;
ikegami
  • 367,544
  • 15
  • 269
  • 518