Substituindo todos os dois pontos por traços em um conjunto de arquivos?

0

Eu tentei substituir todos os dois pontos com traços em nomes de arquivos de algumas subpastas usando o seguinte comando:

find . -type f -name "*:*" -exec rename -n 's/:/-/g' {} +

No entanto, recebo um erro dizendo

rename: not enough arguments

Do googling, parece que isso é porque eu tenho uma versão diferente de renomear que o necessário para o comando acima. Então, como posso 'converter' este comando para um que funcione com a minha versão renomeada?

Minha versão renomeada é 'renomear do util-linux 2.28.2'

    
por eurocoder 29.08.2017 / 17:30

2 respostas

3

Sim, existem duas variantes principais não relacionadas e completamente incompatíveis de um comando rename em sistemas Linux.

Um perl um (iniciado como um script de exemplo décadas atrás, foi enviado junto com perl por um longo tempo, e você o encontra hoje em dia como um ou vários pacotes separados com algumas extensões). Esse é chamado rename ou às vezes prename em sistemas em que rename é outra coisa.

Esse é o que a linha de comando está esperando.

E há um utilitário rename muito limitado em util-linux . Esse é às vezes chamado de rename.ul em sistemas em que rename é o perl ' rename .

Com esse, você só pode substituir uma ocorrência de uma string por outra. Você poderia fazer -execdir rename : - {} + , mas isso só substituiria dois pontos ( 12:30:00.log - > 12-30:00.log ).

Aqui, você poderia implementar rename manualmente:

find . -name '*:*' -type f -print0 | perl -0ne '
  rename $_, s{[^/]+$}{$& =~ y/:/-/r}res or warn "rename $_: $!"'

(certificando-se de que : s sejam substituídos por - apenas no nome base dos arquivos, como se os diretórios contivessem : , isso falharia).

Ou usando um shell em vez de perl para fazer a substituição e chamar mv para a renomeação (aqui usando bash e o operador de expansão de parâmetro ${var//pattern/replacement} ksh, você pode substituir bash por ksh ou zsh se você não tiver bash ):

find . -name '*:*' -type f -exec bash -c '
  for file do
    base=${file##*/}
    mv "$file" "${file%/*}/${base//:/-}"
  done' bash {} +

Ou use zsh e sua função zmv :

autoload zmv
zmv '(**/)(*:*)(#qD.)' '$1${2//:/-}'
    
por 29.08.2017 / 17:52
1

Sem rename :

find . -type f -name '*:*' -execdir bash -c 'echo mv "$1" "${1//:/-}"' bash {} \;

Tente como mostrado, depois remova echo se achar que faz a coisa certa.

Isso usa -execdir para executar bash -c 'mv "$1" "${1//:/-}"' com cada nome de arquivo encontrado como um argumento. O shell interno criado por bash -c receberá um nome em $1 e ${1//:/-} será expandido para esse nome com todos os : substituídos por - .

(O bash final no final do comando é o que será dado a $0 dentro do sub-conjunto bash -c .)

    
por 29.08.2017 / 17:46