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.3
antes defile.log.1
ser renomeado parafile.log.2
. Adicione.
se você quiser renomear apenas arquivos regulares (mas provavelmente você desejaria adicionar uma opção-o-nT
assumindo o GNUmv
) eD
se você também quiser renomear oculto arquivos. -
-f
desativa a salvaguarda que cancelaria esse comando quando um arquivo fosse renomeado para um arquivo existente que atrapalharia nossofile.log.1
,file.log.2
exemplo acima. Ele ainda protegeria contra ofoo.log.1
e ofoo.log.01
sendo 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.