Você estava muito perto.
seq 15 -1 1 | xargs -I@ sh -c 'mv @_* @'
Você precisa atrasar a interpretação (expansão) do *
até depois da substituição de @ .
(Mas você já entendeu que esse era o problema, né?)
Eu tenho informado de nunca incorporar um nome de arquivo desconhecido
(ou outra string de substituição) diretamente em uma linha de comando do shell.
O exemplo acima é provavelmente bastante seguro,
porque você sabe o que as cordas vão ser
15 , 14 ,…, 3 , 2 e 1 .
Mas usando o exemplo acima como um modelo para comandos mais complexos
pode ser perigoso.
Um arranjo mais seguro seria
seq 15 -1 1 | xargs -I@ sh -c 'mv "$1"_* "$1"' x-sh @
onde x-sh é uma string arbitrária
que será usado para rotular quaisquer mensagens de erro emitidas pelo shell chamado.
Isso é equivalente ao meu primeiro exemplo, exceto,
em vez de incorporar as strings (representadas por @ )
diretamente no comando shell,
injeta-os fornecendo o @ como um argumento para o shell,
e, em seguida, referenciá-los como "$1" .
P.S. Você sugeriu executar o comando seq no sentido inverso
( seq 15 -1 1 , que gera 15 , 14 ,…, 3 , 2 , 1
em vez de 1 , 2 , 3 ,…, 14 , 15 ) e ninguém mencionou.
Esta seria uma parte importante da resposta
se os nomes dos arquivos forem iguais a 1foo.txt , 2bar.asc e 13test.png , etc. (com vários caracteres aparecendo após o número, em vez de sempre _ ).
Nesse caso, o comando seria mv "$1"* "$1" (sem o _ ),
e, se você fez 1 primeiro, então o comando mv 1* 1
varreria todos os arquivos 10quick* , 11brown* , 12fox* , etc.
junto com os arquivos 1foo* .
Mas
seq 1 15 | xargs -I@ sh -c 'mv "$1"_* "$1"' x-sh @
deve ser seguro.
P.P.S. O comando seq não é especificado pelo POSIX.
Nem a expansão de contraventamento no shell.
Uma solução compatível com POSIX pode ser construída
combinando a resposta de Grawity a essa pergunta
com esta outra resposta por Adam Katz :
i=1
while [ "$i" -le 15 ]
do
mv "${i}"_* "$i"
i=$((i+1))
done