Bash脚本生成视频HTML页面报错求助:无法创建日期页面
问题:Bash脚本生成HTML页面失败,报错"command not found"
需求背景
我正在编写Bash脚本,用于为树莓派上motion摄像头生成的视频生成带链接的HTML页面,搭配lighttpd使用,需轻量化以降低Pi负载,计划凌晨通过cron自动运行。核心需求:
- 按日期归类视频链接,减少单页链接数量
- 生成索引页,显示各日期对应的视频数量(格式示例:
01/04/2024 - 10 videos) - 每日页面展示缩略图、时间、时长、下载链接(格式示例:
thumbnail - time - length - download link)
目前脚本可正常生成缩略图,但无法生成HTML页面,报错如下:
./test2.sh: line 128: 2024-03-25.html: command not found ./test2.sh: line 128: : No such file or directory
视频文件名格式为yyyy-mm-dd-hh-mm-ss,脚本中的echo语句为测试用,后续会移除。
问题原因
报错源于脚本最后一行的重定向逻辑:
> "$("${day}.html")"
此处错误使用了命令替换$(),系统会把${day}.html当作命令执行,而非作为文件名。正确写法应为直接使用"${day}.html",无需命令替换。
此外还有两处逻辑缺陷:
- 当前脚本将所有视频的HTML内容存入
$items_html,生成每日页面时,每个页面会包含所有日期的视频,而非对应日期的视频 - 缺少索引页的生成逻辑
修复后的完整脚本
#!/bin/sh set -e script_dir=$(dirname "$(readlink -f "$0")") cd "$script_dir" || exit # 目录配置 videos_dir="/home/allan/Documents/videos/" thumbs_dir="/home/allan/Documents/thumbnails/" html_dir="./html" # 新增:存放生成的HTML文件的目录 mkdir -p "$videos_dir" mkdir -p "$thumbs_dir" mkdir -p "$html_dir" # 创建HTML存储目录 # 声明关联数组,按日期存储对应视频的HTML内容 declare -A day_videos # 遍历所有视频文件 for video_file in "$videos_dir"/*; do # 跳过非文件(如目录) [ -f "$video_file" ] || continue video_name="$(basename "${video_file}")" thumb_name="$(basename "${video_file%.*}.jpg")" thumb_file="$thumbs_dir/$thumb_name" # 生成缩略图(如果不存在) if [ ! -e "$thumb_file" ]; then printf "generating thumbnail: %s\n" "$thumb_name" ffmpeg -loglevel error -i "$video_file" -vf "thumbnail,scale=320:240" -frames:v 1 "$thumb_file" fi # 提取日期和时间部分 IFS='-' read -r year month day hour min sec <<< "$video_name" video_date="${year}-${month}-${day}" video_time="${hour}:${min}:${sec}" # 获取并格式化视频时长 video_length=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$video_file") video_length=$(printf "%02d:%02d:%02d" $(echo "$video_length" | awk '{split($1,a,"."); print int(a[1]/3600), int(a[1]%3600/60), int(a[1]%60)}')) # 生成单个视频的HTML片段,按日期分类存储 day_videos["$video_date"]+=" <div class='grid-item-container'> <img class='grid-item' src='../${thumb_file}' data='../${video_file}'/> <div class='player-top-bar'> <span class='player-top-bar-text'>${video_time} | ${video_length}</span> <a href='../${video_file}' class='download-link' download>下载</a> </div> </div>" done # 生成索引页 index_html="$html_dir/index.html" cat > "$index_html" <<EOF <html lang='en'> <head> <title>视频索引</title> <meta name='viewport' content='width=device-width, initial-scale=1'> <style> body { font-family: sans-serif; max-width: 800px; margin: 2rem auto; padding: 0 1rem; } .date-link { display: block; padding: 0.5rem; margin: 0.2rem 0; background: #f0f0f0; text-decoration: none; color: #333; border-radius: 4px; } .date-link:hover { background: #e0e0e0; } </style> </head> <body> <h1>视频日期索引</h1> EOF # 遍历日期,生成索引项和每日页面 for date in "${!day_videos[@]}"; do # 统计当前日期的视频数量 video_count=$(echo "${day_videos[$date]}" | grep -o "<div class='grid-item-container'>" | wc -l) # 转换日期格式为dd/mm/yyyy display_date=$(echo "$date" | awk -F'-' '{print $3"/"$2"/"$1}') # 写入索引页链接 echo " <a href='${date}.html' class='date-link'>${display_date} - ${video_count} videos</a>" >> "$index_html" # 生成每日页面 day_html="$html_dir/${date}.html" cat > "$day_html" <<EOF <html lang='en'> <head> <title>视频查看器 - ${display_date}</title> <meta name='viewport' content='width=device-width, initial-scale=1'> <style> .grid-item-container { position: relative; display: flex; align-items: center; justify-content: center; width: 100%; max-height: 100vh; margin-bottom: 1rem; } .grid-item { width: 100%; height: 100%; border-radius: 4px; } .player-top-bar { display: flex; flex-wrap: wrap; gap: 0.5rem; opacity: 0.8; position: absolute; top: 0; left: 0; padding: 0.2rem; } .player-top-bar-text { padding: 0.05em 0.4em; color: hsl(215deg, 40%, 90%); font-size: 0.8rem; background: hsl(215deg, 40%, 8%); border-radius: 2px; } .download-link { padding: 0.05em 0.4em; color: hsl(215deg, 40%, 90%); font-size: 0.8rem; background: hsl(215deg, 60%, 40%); border-radius: 2px; text-decoration: none; } .download-link:hover { background: hsl(215deg, 60%, 50%); } .back-link { display: inline-block; margin: 1rem; padding: 0.5rem 1rem; background: #333; color: white; text-decoration: none; border-radius: 4px; } .back-link:hover { background: #555; } :root { --gridsize: 1; } @media only screen and (min-width: 768px) { :root { --gridsize: 3; } .grid-container { display: grid; grid-template-columns: repeat(var(--gridsize), 1fr); gap: 1rem; } } </style> </head> <body> <a href='index.html' class='back-link'>返回索引</a> <div class='grid-container'> ${day_videos[$date]} </div> <script> document.querySelector('body').addEventListener('click', (event) => { const element = event.target; if (element.className !== 'grid-item') { return; } const videoPath = element.getAttribute('data'); const videoElement = document.createElement('video'); videoElement.className = 'grid-item' videoElement.setAttribute('controls', '') videoElement.setAttribute('autoplay', '') videoElement.setAttribute('data', element.src) const sourceElement = document.createElement('source'); sourceElement.src = videoPath videoElement.appendChild(sourceElement) element.parentNode.replaceChild(videoElement, element); }); </script> </body> </html> EOF done # 关闭索引页的HTML标签 echo "</body></html>" >> "$index_html" echo "HTML页面生成完成,存放在${html_dir}目录下"
修复说明
- 解决报错问题:移除错误的命令替换
$(),直接使用文件名"${day}.html" - 按日期分类视频:使用关联数组
day_videos存储各日期对应的视频HTML片段,确保每个页面只显示对应日期的视频 - 新增索引页生成:遍历所有日期,生成带视频数量的索引链接,日期格式转换为用户需求的
dd/mm/yyyy - 补充功能细节:用
ffprobe获取并格式化视频时长,添加下载链接;优化页面样式,适配移动端和桌面端,添加返回索引的按钮 - 规范文件存储:创建单独的
html目录存放生成的页面,避免文件混乱
内容的提问来源于stack exchange,提问作者Allan
相关产品推荐
相关产品推荐

