Remova certos caracteres dos nomes de arquivos

Remova certos caracteres dos nomes de arquivos

Eu entendo apenas um pouco sobre isso. O comando abaixo remove os espaços de todos os nomes de arquivos.

find . -type f -name "* *.*" -exec bash -c 'mv "$0" "${0// /}"' {} \;

Gostaria que também removesse vírgulas, pontos e parênteses (   ,  ,,  .,  ( e  ) ), mas não sei onde no comando colocar os caracteres que desejo remover.

Responder1

A resposta curta é: o comando para remover espaços, vírgulas, pontos e parênteses de um nome de arquivo (in  $0) é

mv "$0" "${0//[ ,.()]/}"

Mas não use isso…

Resposta mais longa:

  • Seu findcomando diz -name "* *.*". Isso seleciona arquivos cujos nomes incluem pelo menos um espaço seguido de pelo menos um período.  Faz sentido não tentar processar arquivos cujos nomes não contenham espaço(s), pois, se não houver espaços, não há nada a remover. Mas não sei por que esse comando está sendo testado por um período. Ele será renomeado fat cat.txtpara fatcat.txt, mas permanecerá hot dogintacto frank.fur ter.

    Como você deseja renomear arquivos com pontos em seus nomes (para remover os pontos), você deve alterar seu -nameteste para  -name "*[ ,.()]*".

  • Ao lidar com nomes de arquivos que não são conhecidos antecipadamente, é melhor colocá-los  --antes do primeiro nome de arquivo. Pode-se argumentar que isso não é estritamente necessário quando você está fazendo find . … -exec …, mas é um bom hábito adquirir.

  • Se você tiver arquivos chamados fat cat.txte f a t c a t.txt, ambos serão renomeados para fatcat.txt, e o segundo irá superar o primeiro. Passar a -nopção (no-clobber) para mv evitará que isso aconteça. Mas cuidado: isso deixará arquivos com espaços (etc.) em seus nomes e poderá nem mesmo informar que houve um problema!

  • Seu comando atual invoca um novo bashprocesso para cada arquivo. Isso pode fazer com que demore mais do que o necessário. É preferível invocar bashuma vez e depois invocar mvvárias vezes. Então, incorporando tudo o que foi dito acima, temos

    find . -type f -name "*[ ,.()]*" -exec bash -c 'mv -n -- "$1" "${1//[ ,.()/}"' sh {} +
    

    Mas espere! Ainda não terminamos! Não use o acima.

  • Quando findexecuta um comando (com  -exec), ele passa um nome de caminho do arquivo para o comando. Se você tiver um arquivo chamado fat cat.txtem seu diretório atual, findpassará ./fat cat.txtpara o comando bash. O comando acima tentará renomear fat cat.txt( ./fat cat.txt) para  /fatcattxt. Se você estiver executando como root (ou seja,  sudo), isso moverá seus arquivos para o diretório raiz, causando uma grande bagunça. (Lição: não execute comandos sudoa menos que tenha certeza de que precisa deles.) Se você não estiver executando como root, a “boa notícia” é que o comando não fará nada.

    Então, agora, juntando tudo, obtemos

    find . -type f -name "*[ ,.()]*" -exec bash -c 'for f do dir="$(dirname "$f")"; base="$(basename "$f")"; echo mv -n -- "$f" "$dir/${base//[ ,.()]}"; done' sh {} +
    

    Observe que incluí um echocomando acima, como uma medida de “olhe antes de pular”. Se você executar o comando acima, ele mostrará todos os mvcomandos necessários. Se estiver tudo bem para você, execute o comando novamente com o “ echo” removido.


A propósito, o comando que você mostra na pergunta falhará se algum arquivo com um .em seu nome estão em um diretório que possui um espaço em seu nome.

informação relacionada