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