AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / computer / Perguntas / 1590171
Accepted
Brian
Brian
Asked: 2020-10-02 20:27:49 +0800 CST2020-10-02 20:27:49 +0800 CST 2020-10-02 20:27:49 +0800 CST

Bash: Problemas matemáticos de data/hora

  • 772

O script a seguir usa duas entradas sourceFile="${1}"e arquivos trimFile="${2}". O $sourceFileé um arquivo de vídeo que deve ser cortado em vários novos arquivos com base nos dados do arquivo $trimFile. O $trimFileé um arquivo de texto com a seguinte estrutura (arquivo real relacionado a este problema):

00:49:30,00:53:00 DescriptionA
03:33:30,03:38:40 DescriptionB
04:54:32,04:55:37 DescriptionC

O $trimFileusa vírgulas e espaços como delimitadores no script abaixo. Embora bastante óbvio, cada linha representa um clipe a ser criado a partir do arquivo $sourceFile. Além disso, o primeiro campo é a hora inicial do clipe a ser cortado, o segundo campo é a hora final do clipe a ser cortado e o último campo é uma descrição do clipe.

Meu problema não é com o corte do arquivo $sourceFile. Estou tentando renomear os novos clipes com data e hora em relação à data dos arquivos de vídeo originais. Cada um $sourceFilee $trimFileé nomeado como o exemplo a seguir (que são os nomes de arquivo reais que estou usando atualmente): 2017-05-15_14-17-22 (2017-05-16 00-45-41.151674100 -0400) (HEVC27).mp4e 2017-05-15_14-17-22 (2017-05-16 00-45-41.151674100 -0400) (HEVC27).txt, respectivamente. Novamente, embora bastante óbvio, os componentes da data são Year: 2017, Month: 05, Day: 16, Hour: 14, Minute: 17e Second:22(ignore a data entre parênteses, pois é uma referência antiga com a data ajustada errada do UTC).

Deve ficar evidente no script abaixo como a data/hora no arquivo é extraída, bem como a data/hora dentro do arquivo é $trimFileextraída. Para ilustrar o problema, preciso mostrá-lo com e sem algumas linhas comentadas. Aqui está com algumas linhas comentadas (fará sentido quando eu discutir isso a seguir).

01: sourceFile="${1}"
02: trimFile="${2}"
03: 
04: IFS=$'\n'
05: 
06: dos2unix "$trimFile"
07: numberOfSegments=`cat "$trimFile" | wc -l`
08: numberOfSegments=$((numberOfSegments + 1))
09: extension=`echo "$sourceFile" | awk -F'.' '{print $NF}'`
10: 
11: base=`echo "$sourceFile" | sed -e "s|.$extension||g"`
12: 
13: #~/bin/ffmpeg -i "${sourceFile}" -c:v copy "/dev/shm/$base.${extension}"
14: #sourceFile="/dev/shm/$base.${extension}"
15: 
16: # File date/time information
17: origYear="${sourceFile:0:4}"
18: origMonth="${sourceFile:5:2}"
19: origDay="${sourceFile:8:2}"
20: origHour="${sourceFile:11:2}"
21: origMinute="${sourceFile:14:2}"
22: origSecond="${sourceFile:17:2}"
23: 
24: origDate="${origYear}-${origMonth}-${origDay} ${origHour}:${origMinute}:${origSecond}"
25: 
26: for (( i=1;i<="$numberOfSegments";i++ ))
27:     do
28: 
29:         lineEntry=`cat "$trimFile" | head -"$i" | tail -1`
30: 
31:         startHour=`echo "$lineEntry" | awk -F'[:,]' '{print $1}'`
32:         startMinute=`echo "$lineEntry" | awk -F'[:,]' '{print $2}'`
33:         startSecond=`echo "$lineEntry" | awk -F'[:,]' '{print $3}'`
34: 
35:         endHour=`echo "$lineEntry" | awk -F'[:,]' '{print $4}'`
36:         endMinute=`echo "$lineEntry" | awk -F'[:,]' '{print $5}'`
37:         endSecond=`echo "$lineEntry" | awk -F'[:,]' '{print $6}'`
38: 
39:         description=`echo "$lineEntry" | awk -F'[:, ]' '{print $7}'`
40: 
41:         beginSeconds=`awk "BEGIN {print ($startHour*3600+$startMinute*60+$startSecond)}"`
42:         stopSeconds=`awk "BEGIN {print ($endHour*3600+$endMinute*60+$endSecond)}"`
43:         duration=`awk "BEGIN {print $stopSeconds-$beginSeconds}"`
44: 
45:         newDate=$(date -d "@$(( $(date -d "${origDate}" +%s) + ${beginSeconds}))" +'%Y-%m-%d_%H-%M-%S')
46: 
47:         new="${newDate}_${description}"
48:         echo "${lineEntry}"
49:         echo "${origDate}"
50:         echo "${beginSeconds}"
51:         echo "${new}"
52:         echo ""
53:         
54:         #~/bin/ffmpeg -n -vsync drop -fflags +genpts -i "$sourceFile" -ss "$beginSeconds" -t "$duration" -c:v libx265 -crf 27 -preset slow "$new.mkv"
55: 
56: 
57:     done
58:     
59: #rm "/dev/shm/${base}.${extension}"

Quando executo o script neste formulário, obtenho a seguinte saída correspondente às linhas 48-52 do script:

01: 00:49:30,00:53:00 DescriptionA
02: 2017-05-15 14:17:22
03: 2970
04: 2017-05-15_15-06-52_DescriptionA
05: 
06: 03:33:30,03:38:40 DescriptionB
07: 2017-05-15 14:17:22
08: 12810
09: 2017-05-15_17-50-52_DescriptionB
10: 
11: 04:54:32,04:55:37 DescriptionC
12: 2017-05-15 14:17:22
13: 17672
14: 2017-05-15_19-11-54_DescriptionC
15: 
16: 04:54:32,04:55:37 DescriptionC
17: 2017-05-15 14:17:22
18: 17672
19: 2017-05-15_19-11-54_DescriptionC

Como você pode ver, a nova data/hora esperada é exibida corretamente nas linhas 4,9,14 (não tenho certeza porque a última linha do $trimFileé exibida duas vezes, mas isso não é minha preocupação no momento).

O problema está na renomeação real do arquivo quando removo as linhas comentadas (linhas 13, 14, 54, 59) do script para que o script agora fique assim:

01: sourceFile="${1}"
02: trimFile="${2}"
03: 
04: IFS=$'\n'
05: 
06: dos2unix "$trimFile"
07: numberOfSegments=`cat "$trimFile" | wc -l`
08: numberOfSegments=$((numberOfSegments + 1))
09: extension=`echo "$sourceFile" | awk -F'.' '{print $NF}'`
10: 
11: base=`echo "$sourceFile" | sed -e "s|.$extension||g"`
12: 
13: ~/bin/ffmpeg -i "${sourceFile}" -c:v copy "/dev/shm/$base.${extension}"
14: sourceFile="/dev/shm/$base.${extension}"
15: 
16: # File date/time information
17: origYear="${sourceFile:0:4}"
18: origMonth="${sourceFile:5:2}"
19: origDay="${sourceFile:8:2}"
20: origHour="${sourceFile:11:2}"
21: origMinute="${sourceFile:14:2}"
22: origSecond="${sourceFile:17:2}"
23: 
24: origDate="${origYear}-${origMonth}-${origDay} ${origHour}:${origMinute}:${origSecond}"
25: 
26: for (( i=1;i<="$numberOfSegments";i++ ))
27:     do
28: 
29:         lineEntry=`cat "$trimFile" | head -"$i" | tail -1`
30: 
31:         startHour=`echo "$lineEntry" | awk -F'[:,]' '{print $1}'`
32:         startMinute=`echo "$lineEntry" | awk -F'[:,]' '{print $2}'`
33:         startSecond=`echo "$lineEntry" | awk -F'[:,]' '{print $3}'`
34: 
35:         endHour=`echo "$lineEntry" | awk -F'[:,]' '{print $4}'`
36:         endMinute=`echo "$lineEntry" | awk -F'[:,]' '{print $5}'`
37:         endSecond=`echo "$lineEntry" | awk -F'[:,]' '{print $6}'`
38: 
39:         description=`echo "$lineEntry" | awk -F'[:, ]' '{print $7}'`
40: 
41:         beginSeconds=`awk "BEGIN {print ($startHour*3600+$startMinute*60+$startSecond)}"`
42:         stopSeconds=`awk "BEGIN {print ($endHour*3600+$endMinute*60+$endSecond)}"`
43:         duration=`awk "BEGIN {print $stopSeconds-$beginSeconds}"`
44: 
45:         newDate=$(date -d "@$(( $(date -d "${origDate}" +%s) + ${beginSeconds}))" +'%Y-%m-%d_%H-%M-%S')
46: 
47:         new="${newDate}_${description}"
48:         echo "${lineEntry}"
49:         echo "${origDate}"
50:         echo "${beginSeconds}"
51:         echo "${new}"
52:         echo ""
53:         
54:         ~/bin/ffmpeg -n -vsync drop -fflags +genpts -i "$sourceFile" -ss "$beginSeconds" -t "$duration" -c:v libx265 -crf 27 -preset slow "$new.mkv"
55: 
56: 
57:     done
58:     
59: rm "/dev/shm/${base}.${extension}"
60: 
61: 

Os arquivos criados pelo script são nomeados da seguinte forma:

1969-12-31_19-49-30_DescriptionA.mkv
1969-12-31_22-33-30_DescriptionB.mkv
1969-12-31_23-54-32_DescriptionC.mkv

Obviamente, as datas usadas para nomear o arquivo não são nada parecidas com a saída para stout criada quando eu não recodifiquei o vídeo, mas apenas testei se as novas variáveis ​​de data estavam sendo calculadas corretamente.

Então, minha pergunta se resume a isso, por que, depois de fazer algumas contas de data/hora, a data/hora está correta quando ecoada para robusta, mas totalmente errada quando usada para nomear os arquivos uma vez codificados.

Obrigado!

bash shell-script
  • 2 2 respostas
  • 52 Views

2 respostas

  • Voted
  1. Best Answer
    Kamil Maciorowski
    2020-10-02T22:02:16+08:002020-10-02T22:02:16+08:00

    por que, depois de fazer algumas contas de data/hora, a data/hora está correta quando ecoada para robusta, mas totalmente errada quando usada para nomear os arquivos uma vez codificados?

    Ao descomentar

    sourceFile="/dev/shm/$base.${extension}"
    

    você fez as linhas a seguir extrair fragmentos errados.

    origYear="${sourceFile:0:4}"
    origMonth="${sourceFile:5:2}"
    …
    

    Por exemplo, agora $origYearse expande para /dev.

    Eu esperaria date -dlançar erros semelhantes a date: invalid date '/dev-sh-/2 17:05:15'. Talvez o seu date -dnão valide sua entrada (ou você ignorou os erros?).

    Você pode corrigir esse problema específico atribuindo substrings a origYear, origMonthetc. antes de alterar o valor de sourceFile.

    • 2
  2. Brian
    2020-10-03T20:20:18+08:002020-10-03T20:20:18+08:00

    Caso alguém faça referência a esta postagem no futuro, abaixo está o script de trabalho corrigido. Houve erros adicionais além do que foi abordado nesta postagem que também foram corrigidos (ou seja, o comando ffmpeg e a localização de -sse -tdentro do comando.

    01: sourceFile="${1}"
    02: trimFile="${2}"
    03: 
    04: IFS=$'\n'
    05: 
    06: dos2unix "$trimFile"
    07: numberOfSegments=`cat "$trimFile" | wc -l`
    08: numberOfSegments=$((numberOfSegments))
    09: extension=`echo "$sourceFile" | awk -F'.' '{print $NF}'`
    10: 
    11: base=`echo "$sourceFile" | sed -e "s|.$extension||g"`
    12: 
    13: ~/bin/ffmpeg -i "${sourceFile}" -c:v copy "/dev/shm/$base.mkv"
    14: sourceFile="/dev/shm/$base.mkv"
    15: 
    16: # File date/time information
    17: origYear="${sourceFile:9:4}"
    18: origMonth="${sourceFile:14:2}"
    19: origDay="${sourceFile:17:2}"
    20: origHour="${sourceFile:20:2}"
    21: origMinute="${sourceFile:23:2}"
    22: origSecond="${sourceFile:26:2}"
    23: 
    24: origDate="${origYear}-${origMonth}-${origDay} ${origHour}:${origMinute}:${origSecond}"
    25: 
    26: for (( i=1;i<="$numberOfSegments";i++ ))
    27:     do
    28: 
    29:         lineEntry=`cat "$trimFile" | head -"$i" | tail -1`
    30: 
    31:         startHour=`echo "$lineEntry" | awk -F'[:, ]' '{print $1}'`
    32:         startMinute=`echo "$lineEntry" | awk -F'[:, ]' '{print $2}'`
    33:         startSecond=`echo "$lineEntry" | awk -F'[:, ]' '{print $3}'`
    34: 
    35:         endHour=`echo "$lineEntry" | awk -F'[:, ]' '{print $4}'`
    36:         endMinute=`echo "$lineEntry" | awk -F'[:, ]' '{print $5}'`
    37:         endSecond=`echo "$lineEntry" | awk -F'[:, ]' '{print $6}'`
    38: 
    39:         description=`echo "$lineEntry" | awk -F'[:, ]' '{print $7}'`
    40: 
    41:         beginSeconds=`awk "BEGIN {print ($startHour*3600+$startMinute*60+$startSecond)}"`
    42:         stopSeconds=`awk "BEGIN {print ($endHour*3600+$endMinute*60+$endSecond)}"`
    43:         duration=`awk "BEGIN {print $stopSeconds-$beginSeconds}"`
    44: 
    45:         newDate=$(date -d "@$(( $(date -d "${origDate}" +%s) + ${beginSeconds}))" +'%Y-%m-%d_%H-%M-%S')
    46:         newDate=`echo ${newDate}`
    47:         
    48:         new="${newDate}_${description}"
    49:         
    50:         ~/bin/ffmpeg -n -ss "$beginSeconds" -t "$duration" -i "$sourceFile" -c:v copy "$new.mkv"
    51: 
    52:     done
    53:     
    54: rm "/dev/shm/${base}.mkv"
    
    • 0

relate perguntas

  • substituindo zsh por bash no usuário não root

  • Tendo problemas para definir variáveis ​​de ambiente no Terminal no macOS High Sierra

  • Existe um equivalente a cd - para cp ou mv?

  • Notificar-enviar notificações aparecendo na janela

  • como abrir um arquivo de escritório do WSL

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como posso reduzir o consumo do processo `vmmem`?

    • 11 respostas
  • Marko Smith

    Baixar vídeo do Microsoft Stream

    • 4 respostas
  • Marko Smith

    O Google Chrome DevTools falhou ao analisar o SourceMap: chrome-extension

    • 6 respostas
  • Marko Smith

    O visualizador de fotos do Windows não pode ser executado porque não há memória suficiente?

    • 5 respostas
  • Marko Smith

    Como faço para ativar o WindowsXP agora que o suporte acabou?

    • 6 respostas
  • Marko Smith

    Área de trabalho remota congelando intermitentemente

    • 7 respostas
  • Marko Smith

    O que significa ter uma máscara de sub-rede /32?

    • 6 respostas
  • Marko Smith

    Ponteiro do mouse movendo-se nas teclas de seta pressionadas no Windows?

    • 1 respostas
  • Marko Smith

    O VirtualBox falha ao iniciar com VERR_NEM_VM_CREATE_FAILED

    • 8 respostas
  • Marko Smith

    Os aplicativos não aparecem nas configurações de privacidade da câmera e do microfone no MacBook

    • 5 respostas
  • Martin Hope
    CiaranWelsh Como posso reduzir o consumo do processo `vmmem`? 2020-06-10 02:06:58 +0800 CST
  • Martin Hope
    Jim Pesquisa do Windows 10 não está carregando, mostrando janela em branco 2020-02-06 03:28:26 +0800 CST
  • Martin Hope
    v15 Por que uma conexão de Internet gigabit/s via cabo (coaxial) não oferece velocidades simétricas como fibra? 2020-01-25 08:53:31 +0800 CST
  • Martin Hope
    fixer1234 O "HTTPS Everywhere" ainda é relevante? 2019-10-27 18:06:25 +0800 CST
  • Martin Hope
    andre_ss6 Área de trabalho remota congelando intermitentemente 2019-09-11 12:56:40 +0800 CST
  • Martin Hope
    Riley Carney Por que colocar um ponto após o URL remove as informações de login? 2019-08-06 10:59:24 +0800 CST
  • Martin Hope
    zdimension Ponteiro do mouse movendo-se nas teclas de seta pressionadas no Windows? 2019-08-04 06:39:57 +0800 CST
  • Martin Hope
    jonsca Todos os meus complementos do Firefox foram desativados repentinamente, como posso reativá-los? 2019-05-04 17:58:52 +0800 CST
  • Martin Hope
    MCK É possível criar um código QR usando texto? 2019-04-02 06:32:14 +0800 CST
  • Martin Hope
    SoniEx2 Altere o nome da ramificação padrão do git init 2019-04-01 06:16:56 +0800 CST

Hot tag

windows-10 linux windows microsoft-excel networking ubuntu worksheet-function bash command-line hard-drive

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve