Renomear nomes de arquivos em vários diretórios

1

Eu tenho vários diretórios com arquivos fora de seqüência porque os títulos são exibidos antes do número do arquivo. Eu quero combinar e substituir o final de todos os arquivos, menos a extensão, então o número está no começo assim.

A partir disso

A guide to perfect eggs-456704.mp4
Boil an egg-456702.mp4
How to ruin scrambled eggs-456703.mp4
Make green eggs and ham-456701.mp4
Poached eggs-456705.mp4

Para isso:

456701-Make green eggs and ham.mp4
456702-Boil an egg.mp4
456703-How to ruin scrambled eggs.mp4
456704-A guide to perfect eggs.mp4
456705-Poached eggs.mp4

Os títulos são de tamanho aleatório para cada arquivo com espaços, os números são 6 dígitos antes da extensão ".mp4", mas precedidos por um traço após o título.

    
por dawja 16.10.2017 / 15:14

5 respostas

0

Aqui você tem uma maneira de fazer isso. Não foi testado

#!/bin/bash

files=(*file)

for f in "${files[@]}" 
  do 
     get_ext="${f##*.}"
     no_ext="${f%-*}"
     n="${f##*-}" nn="${n%.*}"
     mv "$f" "$nn-$no_ext.$get_ext"
 done
    
por 16.10.2017 / 15:49
1

Usando find e Shell (Bash, ksh, ksh93, mksh, zsh) Pattern substitution expansion .

find * -type f -name "*.mp4" -exec bash -c 'echo mv -v "$1" "${1//[^0-9]}-${1//[\-0-9]}"' _ '{}' \;
  • Com ${1//[^0-9]} , estamos removendo tudo, exceto um número; A // é a sintaxe de substituição global, enquanto / é apenas para a primeira ocorrência do número.

  • Em seguida, um traço / híche - e com ${1//[\-0-9]} estamos removendo tudo o que é - ou número (assumindo apenas um - e a parte numérica no nome dos arquivos).

Usamos -exec no comando acima, que não é seguro por alguns motivos 1 < a href="https://askubuntu.com/q/621132/283843"> 2 e aqui porque com a Expansão de Substituição do Shell, ele assumirá o caminho do arquivo e causará renomeação inesperada + eliminará todos os traços - no nome dos arquivos!

No final, não se esqueça de remover os comandos echo acima nos comandos para ter uma renomeação real onde ela costumava ser executada.

find . -type f -name "*.mp4" -execdir sh -c '
    n="${1##*-}";fn="${1%-*}"; 
    echo mv -v "$1" "${n%.*}-${fn##*/}.mp4" ' _ '{}' \;

Igual ao comando anterior, mas aqui usamos shell (POSIX sh/bash/Korn/zsh) parameter substitution expansion e isso garantirá que o participante mantenha todos os traços - intocados no nome do arquivo, se houver algum a file-with -- here-006.file , exceto o último que deve ser descartado.

Estamos procurando apenas os arquivos -type f terminam com .mp4 e com -execdir , find está alterando o diretório atual para o diretório onde arquivo foi encontrado sh -c '...' dentro desse diretório em si.

  • Com n="${1##*-}" "cut-up-last-prefix": estamos removendo tudo, desde o início do nome do arquivo até o último traço - visto e - em si e atribuído à variável n ; O $1 ou ${1} é o caminho relativo para ./fileName para o diretório atual por -execdir sh -c '...' _ '{}' \; returns.

  • Com fn="${1%-*}" "recortado-para-primeiro-sufixo": Estamos removendo tudo, desde o final do nome do arquivo até o primeiro traço - visto e - em si e atribuído à variável fn .

    Agora, n="456704.mp4" e nf="./A guide to perfect eggs" (assumindo o primeiro arquivo). Então,

  • Com ${n%.*}- , estamos removendo tudo do final do fileName até o primeiro ponto . seen e . e, em seguida, adicionamos um traço - . Portanto, isso resultará apenas em dígitos do nome do arquivo 456704 .

  • Com ${fn##*/}.mp4 , estamos removendo tudo, desde o início do nome do arquivo até a última barra / vista e / e, em seguida, adicionamos .mp4 no final. Então, isso resultará em A guide to perfect eggs.mp4 .

1 Quais são os problemas de segurança e as condições de corrida no uso de find -exec ?
2 Por que usar a ação '-execdir' é insegura para o diretório que está no PATH?

    
por 16.10.2017 / 15:49
0
set "a file blah blah-004.file" \
"b file blah blah blah-002.file" \
"c file blahh blah-003.file" \
"d file blah blah blah blabby blah-001.file" \
"e file blah-005.file"

for name; do
  old=$name                 # save old name
  ext=${name##*.}           # take extension
  name=${name%.*}           # remove extension
  number=${name##*-}        # take number
  name=${name%-*}           # remove number
  new="$number-$name.$ext"  # set new name
  echo mv "$old" "$new"     # test rename
done

Remova o último echo , se funcionar.

    
por 16.10.2017 / 16:01
0

Solução alternativa find + nome do produto ( Perl ) renomeia:

find -type f -exec prename 's/^(.+?)([^\/]+)-([0-9]+)(\.[^.]+)$/$1$3-$2$4/' '{}' \;
    
por 16.10.2017 / 16:30
0

Esta é uma implementação sh portátil.

find . -name "*[0-9].mp4" |
    sed "s/\(.*\/\)\(.*\)-\([0-9]*\)\.mp4/'-.mp4' '-.mp4'/" |
    xargs -p -L 1 mv -v

O comando find é bastante direto: ele retornará apenas .mp4 arquivos que contenham pelo menos um dígito antes da extensão.

O comando sed duplica o nome do arquivo, alocando cada nome de arquivo com aspas simples e, em seguida, o segundo nome do arquivo move a parte do dígito entre o caminho do arquivo relativo e o nome do arquivo (por exemplo, './a/Boil an egg-456707' './a/456707-Boil an egg.mp4' ).

A lista resultante de nomes de arquivos atuais e novos é então passada para o comando xargs , que executará mv -v . A opção -L 1 é necessária para que xarg processe uma linha por vez. Você pode remover a opção -p deste comando e alterar as opções que mv deve usar.

Eu testei essa implementação com sua lista de arquivos no Ubuntu bash , sh e Mac OS High Sierra bash e sh , colocando arquivos em subdiretórios diferentes e adicionando alguns arquivos que não se qualificaram.

    
por 16.10.2017 / 23:22

Tags