Remove a penúltima extensão em um nome de arquivo

5

Suponha uma pasta com muitos arquivos com extensões incorretas, por exemplo

Song1.avi.mp3
Song2.avi.mp3
Song32.web.mp3
Song23.mp4.mp3
Song2a.mp9.mp3

Eu quero remover apenas o segundo campo ( web , avi , mp4 ). Eu sei como fazer com sed mas eu tenho que colocar a extensão

 mv -v $i "$(echo $i|sed 's:.flv::g;s:.avi::g;s:.mp4::g')"

Alguém conhece um método imediato com sed ou awk ou perl para remover apenas a segunda extensão incorreta?

    
por elbarna 23.12.2014 / 01:43

4 respostas

12

Você não precisa de nenhum utilitário externo, você pode fazê-lo com o funcionalidade de manipulação de strings do próprio shell . Isso facilita a quebra de nomes de arquivos com caracteres especiais. E lembre-se de usar citações em torno de substituições de variáveis .

mv -v -- "$i" "${i%.*.*}.${i##*.}"

(Obviamente, este snippet assume que o nome do arquivo contém duas extensões. Se não, ${i%.*.*} seria o nome completo do arquivo.)

    
por 23.12.2014 / 01:53
5

Usando um regex de bash:

f=foo.bar.baz.qux
if [[ $f =~ (.+)\.[^.]+\.([^.]+)$ ]];then
    new="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}"
    if [[ -f "$new" ]]; then
        echo "moving $f would overwrite $new"
    else
        echo mv "$f" "$new"
    fi
fi
mv foo.bar.baz.qux foo.bar.qux

Isso tem a vantagem de não fazer nada se houver menos de dois pontos no nome.

    
por 23.12.2014 / 02:32
5

Se você precisar validar uma correspondência de nome de arquivo, renomeie os arquivos que realmente têm as duas extensões que está tentando modificar.

case ${i##*/} in (*.*.*)
mv -- "$i" "${i%.*.*}.${i##*.}"
;;esac

Entenda que, se você não validar a correspondência e estiver definindo "$i" com um glob como:

for i in *
mv "$i" ...

... então usando o mesmo comando mv como acima (e em outras respostas) pode resultar no arquivo sendo movido para "$i.$i" quando o var se expande para si mesmo se o padrão não não corresponde.

    
por 23.12.2014 / 02:40
4

Fácil renomear com o comando mmv :

$ mmv -n '*.*.*' '#1.#3'

ou com o comando rename :

$ rename -n 's:(.*)\..*(\..*):$1$2:' *
    
por 23.12.2014 / 10:36