Question: I have several hundred files, all with names following the same template :

```
results_20210503_input003_run017_cluster003.txt

```

Is their en efficient way in bash to reorder the substrings ?

```
results_input003_cluster003_run017_20210503.txt

```

I'm thinking of using `cut -f$i` to get each field and then use `mv` to rename the files, but that looks clunky.

Answer: 
Use the [Perl's `rename` commandline](https://unix.stackexchange.com/a/727288/12574) tool (depending on your operating system, that might be called `rename` or `perl-rename` or `prename`):

```
rename 's/(results)(_[0-9]{8})(.*)(\.txt)/$1$3$2$4/' results*txt

```

Use the `-n`-flag for a dry run showing you the renames.

How it works:

* `s/A/B/` - substitute pattern A with pattern B in filenames
* Patterns in parentheses are given an index number as they appear
* Groups are: 1) `results`: literaly "results" ; 2) `_[0-9]{8}`: underscore followed by 8 digits from 0 to 9 ; 3) `.*` .=any character, \*=repeat previous entry as much as possible, i.e. a series of any character ; 4) `\.txt` literally ".txt", `.` needs to be escaped, otherwise would be "any character" as in (3)
* Reorder the pattern groups as desired, reference by `$<ID>`
You don't mention your OS so it's hard to guess what tools may be available to you. I find `mmv` simplest for cases like this. It uses shell globs rather than regular expressions:

```
$ mmv -n 'results_*_*_*_*.txt' 'results_#2_#4_#3_#1.txt'
results_20210503_input003_run017_cluster003.txt -> results_input003_cluster003_run017_20210503.txt

```

Remove the `-n` when you are satisfied with the proposed re-namings.

---

If you really have to do it "*in bash*", then

```
for f in results_*.txt; do 
  IFS=_ read -a elems <<<"${f%.txt}"
  echo mv -n "$f" "results_${elems[2]}_${elems[4]}_${elems[3]}_${elems[1]}.txt"
done
mv -n results_20210503_input003_run017_cluster003.txt results_input003_cluster003_run017_20210503.txt

```

Remove the `echo` to actually rename the files.