You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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",无需命令替换。

此外还有两处逻辑缺陷:

  1. 当前脚本将所有视频的HTML内容存入$items_html,生成每日页面时,每个页面会包含所有日期的视频,而非对应日期的视频
  2. 缺少索引页的生成逻辑

修复后的完整脚本

#!/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}目录下"

修复说明

  1. 解决报错问题:移除错误的命令替换$(),直接使用文件名"${day}.html"
  2. 按日期分类视频:使用关联数组day_videos存储各日期对应的视频HTML片段,确保每个页面只显示对应日期的视频
  3. 新增索引页生成:遍历所有日期,生成带视频数量的索引链接,日期格式转换为用户需求的dd/mm/yyyy
  4. 补充功能细节:用ffprobe获取并格式化视频时长,添加下载链接;优化页面样式,适配移动端和桌面端,添加返回索引的按钮
  5. 规范文件存储:创建单独的html目录存放生成的页面,避免文件混乱

内容的提问来源于stack exchange,提问作者Allan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:37:04