The pattern
'ch '[1-9][!0-9]*'- file.txt' would match all filenames that needs changing (out of the ones that you show), i.e. any filename that starts with ch , followed by a digit between 1 and 9, followed by something that is not a digit. After that, we allow for any characters whatsoever, and the names must end with - file.txt.
We can loop over these files with
for name in 'ch '[1-9][!0-9]*'- file.txt'; do ... done The objective is now to insert a 0 after the ch bit. This can be done by stripping the ch substring off, and replacing it with ch 0:
for name in 'ch '[1-9][!0-9]*'- file.txt'; do newname='ch 0'${name#ch } done The ${name#ch } parameter substitution would expand to 2 - file.txt if $name contained ch 2 - file.txt (it would remove the prefix ch ).
After this, you could just rename the file:
for name in 'ch '[1-9][!0-9]*'- file.txt'; do newname='ch 0'${name#ch } printf 'would rename "%s" into "%s"\n' "$name" "$newname" # mv -i "$name" "$newname" done Remove the # on the line with the commented out mv command after running the loop once to see that it does the correct thing.
The loop above, given the filenames that you show, would output
would rename "ch 2 - file.txt" into "ch 02 - file.txt" would rename "ch 3 - file.txt" into "ch 03 - file.txt" would rename "ch 4a - file.txt" into "ch 04a - file.txt" would rename "ch 5 - file.txt" into "ch 05 - file.txt"