I'm trying to sort the rows of a text file based on an 'index' in another file, such that the text file is arranged, row by row, in the same order as the index file.

The following code achieves what I'm looking to do, but I want to replace file_to_sort.txt with another variable (so that I can pass 2 command line arguments) to make this a general script. I can't figure out how to make the while loop deal with this.

while read line ; do grep $line file_to_sort.txt ; done < ../index.txt

The file to sort looks like so:

Locus ./PAK_01896.fsa GC: 0.401826484018
Locus ./PAK_02014.fsa GC: 0.355555555556
Locus ./PAK_02606.fsa GC: 0.415555555556
Locus ./PAK_03203.fsa GC: 0.391111111111
Locus ./PAU_01961.fsa GC: 0.395555555556
Locus ./PAU_02074.fsa GC: 0.406392694064
Locus ./PAU_02206.fsa GC: 0.353333333333
Locus ./PAU_02775.fsa GC: 0.415555555556
Locus ./PAU_03392.fsa GC: 0.384444444444
Locus ./PLT_01696.fsa GC: 0.42
Locus ./PLT_01716.fsa GC: 0.422222222222
Locus ./PLT_01736.fsa GC: 0.433333333333
Locus ./PLT_01758.fsa GC: 0.426666666667
Locus ./PLT_02424.fsa GC: 0.413333333333
Locus ./PLT_02568.fsa GC: 0.391111111111

And the index order looks like this (and so the output should be the first file, sorted according the the ./xxx_xxxx strings in the second).


I'm sure this is really simple, but I can't see it and whatever I was searching to try and solve this wasn't dragging up the right answers (since I'm sure this has been answered somewhere.

  • how bigs the file. can it fit in memory ? Also in the sort file can there be dupes of the keys ?
    – 123
    Apr 6, 2016 at 8:31
  • @nagu please don't answer questions in the comments. That way, the question will never be marked as answered. Post your comment as an answer instead.
    – terdon
    Apr 6, 2016 at 8:53
  • 1
    Your question is misleading. If you know how to do it why are you using a title like "Sorting one file line by line based on another file" and why are you posting the contents of the files ? That's irrelevant. Also, your while..read..grep is anything but fast. You should use something like awk -F'[/.]' 'NR==FNR{x[$3] = $0;next};($1 in x) {print x[$1]}' "$1" "$2" I'll let you figure out what the $1 and respectively $2 stand for (this is what your question is all about, after all). Apr 6, 2016 at 10:55
  • @123 The file is pretty small (for this particular usage case, though my wanting to generalise it means that I can envisage usage cases in the future where the files could be pretty large). And, again, at least in this particular instance there are no duplicated keys.
    – Joe Healey
    Apr 7, 2016 at 9:00
  • 1
    @don_crissti I thought the title was descriptive of the problem I was trying to solve, and was the types of phrases I was personally searching for when looking for solutions. I gave the file contents simply because I thought it might make the problem that bit clearer. I can edit the question though if people disagree.
    – Joe Healey
    Apr 7, 2016 at 9:03

2 Answers 2


while read LINE; do
    grep "$LINE" "$FILE_TO_SORT" >>"$TMP_FILE"
done <"$INDEX_FILE"


The above script will take 2 arguments and sort the first based on the second, take in consideration that lines not matched by any in the index file will be discarded, also the original file will be replaced by the sorted one. On top of that if you have several lines to be sorted with the same index and want it to be sorted as well you can change the grp line to this grep "$LINE" "$FILE_TO_SORT" | sort -f 4 >>"$TMP_FILE" and it will be sorted by the number (field 4) at the end.

  • To cut out the 'middle man' - is it valid to simply use: while read LINE ; do grep "$LINE" "$1" >> "$3" ; done < "$2" - and then to invoke it with script.sh $1 $2 $3 ?
    – Joe Healey
    Apr 7, 2016 at 8:57
  • Of course you can use the ${1,2} variables directly but I always use named variables because is easier to read specially on long scripts, and also you can pass a third argument to specify an output file, or even remove the redirect after grep and output to stdout, but those are details I left for the OP to decide
    – Dalvenjia
    Apr 7, 2016 at 15:13

if all you want to do is replace the hard coded file name to be sorted and the input file by variables, this will work: input_file="$1"; file_to_sort="$2"; while read line ; do grep $line $file_to_sort ; done < $input_file then, run it by passing ../index.txt and file_to_sort.txt as arguments to the script.

also, note that in your script, if there are lines in the file_to_sort that do not match any lines in index.txt, those will be omitted in the output.

You must log in to answer this question.

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