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
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.
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?
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.
Solução alternativa find + nome do produto ( Perl ) renomeia:
find -type f -exec prename 's/^(.+?)([^\/]+)-([0-9]+)(\.[^.]+)$/$1$3-$2$4/' '{}' \;
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.