Batch renomeia arquivos que terminam em um ponto

2

Eu tenho um grande servidor de arquivos unix, com um único grande compartilhamento SMB. Serve para clientes Mac, Linux e Windows. Uma grande parte dos arquivos nesta caixa foram migrados de um Mac Xserve. Uma das formas de backup do compartilhamento é por meio de uma caixa do Windows. Esse software de backup em particular falha se houver caracteres que ele não goste nos nomes de arquivos.

Consegui corrigir a maioria dos problemas de nome de arquivo, mas estou lutando com arquivos que terminam em um ponto. Por exemplo:

  • filename.
  • newfile.txt.
  • stupid old file.

Estou tentando encontrar alguma maneira de renomear em lote todos os arquivos que terminam em um ponto com o mesmo nome sem o ponto. Então, filename. se torna filename

find . -name "*."

trabalha para encontrar os arquivos. Eu tentei canalizar através do sed:

find . -name "*." | sed 's/.$//'

que faz o trabalho no console, mas na verdade não renomeia os arquivos. Essa é a parte que estou lutando.

    
por user3408072 26.03.2014 / 00:51

3 respostas

4

Se você tiver a versão do script Perl de rename (chamada rename ou prename ):

rename 's/\.$//' *.

ou a versão util-linux (chamada rename ou rename-ul ):

 rename . '' *.

Se você executar o comando sem argumentos e obter algo semelhante a:

Usage: rename [-v] [-n] [-f] perlexpr [filenames]

então é a versão do script Perl.

Algo como:

rename.ul: not enough arguments

Usage: rename.ul [options] expression replacement file...

Options: -v, --verbose explain what is being done -V, --version
output version information and exit -h, --help display this help and exit

significa que é a versão util-linux.

    
por 27.03.2014 / 17:49
0

Meio que hacky, mas deve funcionar:

Se você quiser renomear os arquivos E diretórios com pontos à direita:

    find . -name "*." -print0 | xargs -0 -n 1 my_rename.sh

OU se você quiser renomear apenas os arquivos:

    find . -name "*." -type f -print0 | xargs -0 -n 1 my_rename.sh

Em que my_rename.sh script é apenas:

#!/bin/bash
mv "$1" "${1%%.}"

(Também não esqueça de tornar o script executável: chmod +x my_rename.sh ) 2

    
por 26.03.2014 / 01:42
0

Isso parece que deve fazer o trabalho:

find . -type f -name '*\.' -exec bash -c 'mv "$1" "${$1%.}"' _ {} \;

Isso limita a localização a apenas arquivos com um ponto final (caso contrário, ele corresponde ao diretório de trabalho atual, '.') e, em seguida, executa o fragmento de shell entre aspas ( mv "$1" "${$1%.}" ) para cada nome de arquivo encontrado. Dentro do fragmento de shell, ele usa expansão e substituição de parâmetro bash para remover o '.' Final. O outro ruído de linha no final é necessário para o find -exec: {} é o texto correspondente do find, \; é necessário para terminar a string execut, e eu acredito que o _ diz ao exec para passar { } como um parâmetro ( $1 ) para o comando sh . Para ser honesto, este uso específico de -exec é novo para mim, eu achei aqui .

O bit de substituição bash é bastante direto, e eu uso isso com bastante frequência para renomear arquivos, por exemplo, FILENAME=foo.JPG; mv ${FILENAME} ${FILENAME%.JPG}.jpg removerá o '.JPG' de FILENAME e substituirá por '.jpg'

Se você ainda quiser usar o sed em vez da expansão do bash, parece que ele faria o trabalho:

find . -type f -name '*\.' -exec sh -c 'mv "{}" "$(echo {} | sed s/\.$// )"' \;

Primeiro tentei resolver isso sem fazer com que -exec invocasse sh -c , mas não gostasse de {} sair da expansão ao tentar executar o sed (ou com o exemplo de substituição bash antes).

Observe também que você precisa "" colocar os nomes dos arquivos que você está expandindo (por exemplo, {} ou $ 1, dependendo do exemplo), pois os arquivos de amostra têm espaços neles. Isso ainda pode ser interrompido, dependendo de quais caracteres especiais estão no seu arquivo (por exemplo, um "no nome do arquivo causará problemas).

    
por 26.03.2014 / 01:41

Tags