Reverse Order Of List

Note: since writing this memo I re-discovered tac (reverse cat) in coreutils!

Sometimes it is useful to quickly reverse the order of a list (often lines of text) in a bash shell or script. Unfortunately the tools that seem most appropriate, sort and rev, aren't. sort -r reverses the comparison logic whilst sorting, rather than just swapping last to first, etc., and rev will only reverse the characters on a line.

Bash Array

Using a bash array and the seq utility is one solution.

  1. Read the lines into an array
  2. Iterate the array, last to first

The problem was reversing the list of a batch of (quilt) source-code patches so they could be removed in the reverse order that they were applied:

$ for patch in $(grep -v '^#'  debian/patches/series); do echo "Applying $patch"; patch -p1 <debian/patches/${patch}; done

The way to invert the list is:

$ patches=($(grep -v '^#' debian/patches/series)); for patch in $(seq $((${#patches[@]} - 1)) -1 0); \
  do echo "Reversing ${patches[$patch]}"; patch -R -p1 <debian/patches/${patches[$patch]}; done

Note the use of seq [first] [increment] [last]. In this case first is the number of elements in the array (${#patches[@]} - 1), increment is -1, and last is 0.


The proper way though, is of course:

$ for patch in $(grep -v '^#' debian/patches/series | tac); \
  do echo "Reversing ${patches[$patch]}"; patch -R -p1 <debian/patches/${patches[$patch]}; done