AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / computer / 问题 / 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:日期/时间数学问题

  • 772

以下脚本接受两个输入,sourceFile="${1}"并且trimFile="${2}". 这$sourceFile是一个视频文件,将根据$trimFile. 这$trimFile是一个具有以下结构的文本文件(与此问题相关的实际文件):

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

在下面$trimFile的脚本中使用逗号和空格作为分隔符。虽然相当明显,但每一行都代表一个要从$sourceFile. 进一步地,第一个字段是要修剪的剪辑的开始时间,第二个字段是要修剪的剪辑的结束时间,最后一个字段是剪辑的描述。

我的问题不在于修剪$sourceFile. 我正在尝试使用相对于原始视频文件日期的日期和时间重命名新剪辑。每个$sourceFile和$trimFile的命名类似于以下示例(这是我目前使用的实际文件名):2017-05-15_14-17-22 (2017-05-16 00-45-41.151674100 -0400) (HEVC27).mp4和2017-05-15_14-17-22 (2017-05-16 00-45-41.151674100 -0400) (HEVC27).txt,分别。同样,虽然相当明显,日期组件是Year: 2017, Month: 05, Day: 16, Hour: 14, Minute: 17, 和Second:22(忽略日期是括号,因为它是带有错误 UTC 调整日期的旧参考)。

在下面的脚本中,如何提取文件中的日期/时间以及如何提取文件中的日期/时间应该很明显$trimFile。为了说明这个问题,我需要在注释掉和不注释掉某些行的情况下显示它。在这里,某些行被注释掉了(这将在我接下来讨论的时候有意义)。

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}"

当我以这种形式执行脚本时,我得到以下与脚本中第 48-52 行相对应的输出:

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

如您所见,预期的新日期/时间在第 4、9、14 行中正确输出(我不确定为什么最后一行$trimFile输出两次,但目前这不是我关心的问题)。

问题在于当我从脚本中删除注释行(第 13、14、54、59 行)时文件的实际重命名,因此脚本现在看起来像这样:

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: 

脚本创建的文件命名如下:

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

显然,用于命名文件的日期与我没有重新编码视频而只是测试新日期变量是否正确计算时创建的输出不同。

所以,我的问题归结为这个,为什么在做了一些日期/时间数学之后,日期/时间在回显到粗壮时是正确的,但在用于命名编码后的文件时却大错特错。

谢谢!

bash shell-script
  • 2 2 个回答
  • 52 Views

2 个回答

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

    为什么在进行一些日期/时间数学运算之后,日期/时间在回显到粗壮时是正确的,但在用于命名编码后的文件时却严重错误?

    通过取消注释

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

    您使后面的行提取了错误的片段。

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

    例如,现在$origYear扩展为/dev.

    我希望date -d抛出类似于date: invalid date '/dev-sh-/2 17:05:15'. 也许您date -d没有验证其输入(或者您是否忽略了错误?)。

    您可以通过在更改 的值之前将子字符串分配给等origYear来解决此特定问题。origMonthsourceFile

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

    如果将来有人引用这篇文章,下面是更正的工作脚本。除了在这篇文章中解决的问题之外,还有其他错误也得到了纠正(即 ffmpeg 命令以及命令的位置-ss和命令-t中的位置。

    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

相关问题

  • 在非 root 用户上用 bash 替换 zsh

  • 在 macOS High Sierra 的终端中设置环境变量时遇到问题

  • 对于 cp 或 mv,是否有等同于 cd - 的东西?

  • Notify-发送窗口下出现的通知

  • 如何从 WSL 打开 office 文件

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何减少“vmmem”进程的消耗?

    • 11 个回答
  • Marko Smith

    从 Microsoft Stream 下载视频

    • 4 个回答
  • Marko Smith

    Google Chrome DevTools 无法解析 SourceMap:chrome-extension

    • 6 个回答
  • Marko Smith

    Windows 照片查看器因为内存不足而无法运行?

    • 5 个回答
  • Marko Smith

    支持结束后如何激活 WindowsXP?

    • 6 个回答
  • Marko Smith

    远程桌面间歇性冻结

    • 7 个回答
  • Marko Smith

    子网掩码 /32 是什么意思?

    • 6 个回答
  • Marko Smith

    鼠标指针在 Windows 中按下的箭头键上移动?

    • 1 个回答
  • Marko Smith

    VirtualBox 无法以 VERR_NEM_VM_CREATE_FAILED 启动

    • 8 个回答
  • Marko Smith

    应用程序不会出现在 MacBook 的摄像头和麦克风隐私设置中

    • 5 个回答
  • Martin Hope
    CiaranWelsh 如何减少“vmmem”进程的消耗? 2020-06-10 02:06:58 +0800 CST
  • Martin Hope
    Jim Windows 10 搜索未加载,显示空白窗口 2020-02-06 03:28:26 +0800 CST
  • Martin Hope
    v15 为什么通过电缆(同轴电缆)的千兆位/秒 Internet 连接不能像光纤一样提供对称速度? 2020-01-25 08:53:31 +0800 CST
  • Martin Hope
    fixer1234 “HTTPS Everywhere”仍然相关吗? 2019-10-27 18:06:25 +0800 CST
  • Martin Hope
    andre_ss6 远程桌面间歇性冻结 2019-09-11 12:56:40 +0800 CST
  • Martin Hope
    Riley Carney 为什么在 URL 后面加一个点会删除登录信息? 2019-08-06 10:59:24 +0800 CST
  • Martin Hope
    zdimension 鼠标指针在 Windows 中按下的箭头键上移动? 2019-08-04 06:39:57 +0800 CST
  • Martin Hope
    jonsca 我所有的 Firefox 附加组件突然被禁用了,我该如何重新启用它们? 2019-05-04 17:58:52 +0800 CST
  • Martin Hope
    MCK 是否可以使用文本创建二维码? 2019-04-02 06:32:14 +0800 CST
  • Martin Hope
    SoniEx2 更改 git init 默认分支名称 2019-04-01 06:16:56 +0800 CST

热门标签

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

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve