Eri molto vicino.
seq 15 -1 1 | xargs [email protected] sh -c 'mv @_* @'
Devi ritardare l'interpretazione (espansione) del *
fino a dopo il @
avvenuta la sostituzione. (Ma hai già capito che era quello il problema, giusto?)
Mi è stato consigliato di non incorporare mai un nome file sconosciuto (o altra stringa di sostituzione) direttamente in una riga di comando della shell. L'esempio sopra è probabilmente abbastanza sicuro, perché sai quali saranno le stringhe —15
, 14
, …, 3
, 2
e 1
. Ma usare l'esempio precedente come modello per comandi più complessi può essere pericoloso. Un accordo più sicuro sarebbe
seq 15 -1 1 | xargs [email protected] sh -c 'mv -- "$1"_* "$1"' x-sh @
dove x-sh
è una stringa semi-arbitraria che verrà utilizzata per etichettare eventuali messaggi di errore emessi dalla shell invocata. Questo è equivalente al mio primo esempio, eccetto,piuttosto che incorporare le stringhe (rappresentate da @
)direttamente nel comando shell, li inserisce fornendo @
come argomento per la shell, quindi facendovi riferimento come "$1"
.
P.S. Hai suggerito di eseguire il seq
comando al contrario(seq 15 -1 1
, che genera 15
, 14
, …, 3
, 2
, 1
anziché 1
, 2
, 3
, …, 14
, 15
) e nessuno ne ha parlato. Questa sarebbe una parte importante della risposta se i tuoi nomi di file fossero come 1foo.txt
, 2bar.asc
e 13test.png
, ecc. (con vari caratteri che compaiono dopo il numero, invece che sempre _
). In tal caso, il comando sarebbe mv "$1"* "$1"
(senza _
), e, se hai fatto 1
prima, poi il comando mv 1* 1
spazzerebbe via tutto il 10quick*
, 11brown*
, 12fox*
, ecc., insieme al 1foo*
File. Ma
seq 1 15 | xargs [email protected] sh -c 'mv -- "$1"_* "$1"' x-sh @
dovrebbe essere al sicuro.
PPS Il seq
comando non è specificato da POSIX. Nemmeno l'espansione del tutore nel guscio. Una soluzione conforme a POSIX può essere costruita combinando la risposta di Grawity a questa domanda con quest'altra risposta di Adam Katz:
i=1
while [ "$i" -le 15 ]
do
mv -- "${i}"_* "$i"
i=$((i+1))
done
P.P.P.S. Non è fondamentale quando sai che i nomi dei file iniziano con caratteri alfanumerici (cioè lettere e cifre), ma, in casi più generali, dovresti usare --
tra il nome del comando e gli argomenti. Ciò migliora la gestione dei nomi di file che iniziano con un trattino. Il --
dice al comando di trattare l'argomento (il nome del file)come un argomento. Senza di esso, tale argomento potrebbe essere trattato come una stringa di opzioni.
Basta non usare xargs
per quello. Usa un for
ciclo:
for i in $(seq 1 15); do
mv ${i}_* $i
done
Ancora meglio è usare l'espansione delle parentesi graffe invece di seq
:
mkdir {1..15}
for i in {1..15}; do
mv ${i}_* $i
done