com zsh :
autoload zmv # best in ~/.zshrc
zmv -n -f '(*.log.)(<->)(#qnOn)' '$1$(($2+1))'
(remova o -n se satisfeito com o resultado)
-
<->corresponde a qualquer número decimal -
(#qnOn): qualificador glob aqui para classificar numericamente a lista de arquivos (n) na ordem inversa pelo nome (On), entãofile.log.2é renomeado parafile.log.3antes defile.log.1ser renomeado parafile.log.2. Adicione.se você quiser renomear apenas arquivos regulares (mas provavelmente você desejaria adicionar uma opção-o-nTassumindo o GNUmv) eDse você também quiser renomear oculto arquivos. -
-fdesativa a salvaguarda que cancelaria esse comando quando um arquivo fosse renomeado para um arquivo existente que atrapalharia nossofile.log.1,file.log.2exemplo acima. Ele ainda protegeria contra ofoo.log.1e ofoo.log.01sendo renomeados parafoo.log.2.
Recursivamente:
zmv -n -f '(**/)(*.log.)(<->)(#qnOn)' '$1$2$(($3+1))'
De bash ou sh ou ksh :
zsh << 'EOF'
autoload zmv
zmv -n -f '(*.log.)(<->)(#qnOn)' '$1$(($2+1))'
EOF
Com bash e sem usar zsh , e se você tiver o GNU ls e o GNU mv e a lista de arquivos não for muito grande, você pode fazer algo com:
shopt -s failglob
shopt -s extglob
export LC_ALL=C
eval "files=($(
ls --quoting-style=shell-always -rvd -- *.log.+([[:digit:]])))"
for f in "${files[@]}"; do
echo mv -nT -- "$f" "${f%.*}.$((10#${f##*.} + 1))"
done
(remova echo quando satisfeito).
Recursivamente, com GNU bash , GNU find , GNU mv e GNU sort , apenas para arquivos regulares:
export LC_ALL=C
while IFS= read -rd '' -u3 file; do
echo mv -nT "$file" "${file%.*}.$((10#${file##*.} + 1))"
done 3< <(
find . -name '.?*' -prune -o -regex '.*\.log\.[0-9]+' -type f -print0 |
sort -rzV)
mv -n é uma extensão do GNU para evitar a destruição de arquivos existentes e -T para remover a ambigüidade entre mover para e mover para quais mv sofrem de. No entanto, observe que quando um arquivo não é renomeado por causa de -n , você não recebe nenhum erro sobre isso.