Eu tenho um script bash que renomeia arquivos em uma pasta de acordo com a entrada de um prompt de comando:
echo "Please rename and press enter" read rename
if [ -z "$rename" ]; then
printf "no caption was selected, aborting!\n"
exit 1
fi
printf "rename is $rename\n" count=1
for i in *.jpg; do
j=printf "%04d" $count
j="$rename"$j".jpg"
count=$((count + 1))
mv "$i" $j
done
fi
shift
done
Como posso modificar este script para que os arquivos da pasta sejam renomeados de acordo com seu tamanho?
Se eu classificar os arquivos de acordo com o tamanho, eles ficarão assim na pasta:
a009 978kb
a001 567kb
a003 499kb
a008 432kb
Então, quero que os arquivos resultantes sejam renomeados:
a001 978kb
a002 567kb
a003 499kb
a004 432kb
Responder1
Algo assim:
echo "Please rename and press enter"
read rename
ls |
# prepend filename with file size in bytes
parallel stat -c %s,,sep,,%n -- |
# sort by number
sort -n |
# rename to sequencenumber followed by size in bytes
parallel -q --colsep ,,sep,, mv {2} "$rename"{#}_{1}
Responder2
O truque principal é substituir
for i in *.jpg
com
for i in $(ls -S *.jpg)
no entanto, como apontou Kusalananda, isso pressupõe nomes de arquivos "educados" (sem espaços, sem caracteres de controle), então aqui está uma abordagem diferente:
count=1
ls -S --escape *.jpg | while read f; do
n=$(printf "%04d" $count)
((count++))
mv --no-clobber "$f" "$rename$n.jpg"
done
-S
classifica diminuindo o tamanho do arquivo
--escape
evita que nomes com novas linhas incorporadas causem danos
--no-clobber
evita a substituição dos arquivos de destino caso o script seja executado duas vezes
A resposta de PS Ole Tange é uma maneira muito eficiente de fazer o mesmo, mas você provavelmente não verá a diferença, a menos que renomeie rotineiramente milhares de arquivos.
Responder3
Na zsh
casca:
typeset -Z 3 count=0
for name in *.jpg(.DNOL); do
count=$(( count + 1 ))
mv -i -- "$name" "a$count.jpg"
done
Isso iteraria todos os arquivos regulares com um .jpg
sufixo de nome de arquivo no diretório atual, na ordem do maior para o menor. Para cada arquivo, ele seria renomeado para aNNN.jpg
onde NNN
está a contagem inteira preenchida com zero de arquivos processados até o momento.
O (.DNOL)
qualificador glob ordena os nomes de arquivos correspondentes na ordem correta usando OL
("inverte a ordem por comprimento") e seleciona apenas arquivos regulares (incluindo nomes ocultos) usando .D
("arquivos regulares e arquivos de ponto"). Isso N
faz com que o padrão se expanda para nada se não houver um nome correspondente ("null glob").
Isso funcionaria em todos os nomes de arquivos válidos em qualquer sistema Unix zsh
instalado.
Para usar isso de bash
:
zsh -c 'typeset -Z 3 count=0
for name in *.jpg(.DNOL); do
count=$(( count + 1 ))
mv -i -- "$name" "a$count.jpg"
done'
Se você tiver uma variável $rename
que deseja passar como prefixo de nome de arquivo em vez de usar a
:
zsh -c 'typeset -Z 3 count=0
for name in *.jpg(.DNOL); do
count=$(( count + 1 ))
mv -i -- "$name" "$1$count.jpg"
done' zsh "$rename"
Observe que a zsh
última linha não é um erro de digitação e que o valor de $rename
é usado como $1
dentro do zsh -c
script.