Infelizmente, os curingas são bastante limitados. Mas isso pode ser feito com alguns comandos extras. Primeiro, você pode percorrer os arquivos com for :
bash$ ls -1
hello.txt
help.txt
heroes.txt
bash$ for f in *; do echo "$f"; done
hello.txt
help.txt
heroes.txt
Você também pode fazer uma filtragem inicial usando *.txt em vez de apenas * . Certifique-se de citar a variável para evitar que espaços ou caracteres especiais em nomes de arquivos quebrem o comando.
Agora você pode substituir uma string por outra com sed (a barra invertida é necessária porque o ponto tem um significado especial sem ela , e o cifrão depois significa "fim da string"):
bash$ for f in *; do echo "$f" | sed s/\.txt$/_copy.txt/; done
hello_copy.txt
help_copy.txt
heroes_copy.txt
Você pode facilmente transformar isso em um comando . Por exemplo, um mv (vamos ver primeiro como é possível obter um echo extra):
bash$ for f in *; do echo mv "$f" 'echo "$f" | sed s/\.txt$/_copy.txt/'; done
mv hello.txt hello_copy.txt
mv help.txt help_copy.txt
mv heroes.txt heroes_copy.txt
Tudo parece bom, então vamos fazer isso de verdade agora:
bash$ for f in *; do mv "$f" 'echo "$f" | sed s/\.txt$/_copy.txt/'; done
bash$ ls -1
hello_copy.txt
help_copy.txt
heroes_copy.txt
Você pode até mesmo desfazer a renomeação usando sed s/_copy\.txt$/.txt/ : -)