rokkonet

PC・Androidソフトウェア・アプリの開発・使い方に関するメモ

うちのTV録画ファイル情報を納めたテキストファイルから検索文字列を含む行を削除するシェルスクリプト

2025 Nov. 15.
2025 Aug. 15.

delete_recorded_infomation_lines.sh

#!/usr/bin/env bash
# 2025 Nov. 15.
# 2025 Aug. 15.

set -euo pipefail

usage() {
  cat << EOF
Usage: $0 -d VideoRoot [-e ExcludeDir] -k KeyWord

  -d  VideoRoot   : 探索を開始するディレクトリパス
  -e  ExcludeDir  : 除外するディレクトリパス(VideoRoot 以下の相対 or 絶対指定可、任意)
  -k  KeyWord     : ファイルから削除したい行に含まれる文字列

例:
  $0 -d /mnt/videos -e /mnt/videos/exclude -k ERROR123
  $0 -d /mnt/videos -k ERROR123
EOF
  exit 1
}

# 変数初期化(set -u 対策)
VideoRoot=''
ExcludeDir=''
KeyWord=''

# 引数をパース
while getopts "d:e:k:" opt; do
  case "$opt" in
    d) VideoRoot=$OPTARG   ;;
    e) ExcludeDir=$OPTARG  ;;
    k) KeyWord=$OPTARG     ;;
    *) usage               ;;
  esac
done

# 必須オプションチェック(-e は任意)
if [ -z "$VideoRoot" ] || [ -z "$KeyWord" ]; then
  echo "Error: -d と -k は必須です" >&2
  usage
fi

# VideoRoot がディレクトリか確認
VideoRoot="${VideoRoot%/}"
if [ ! -d "$VideoRoot" ]; then
  echo "Error: ${VideoRoot} がディレクトリではありません" >&2
  exit 1
fi

# ExcludeDir が指定されていれば正規化(相対指定は VideoRoot 以下とみなす)して存在確認
if [ -n "$ExcludeDir" ]; then
  # 末尾スラッシュ除去
  ExcludeDir="${ExcludeDir%/}"
  # 相対パスなら VideoRoot 以下に補完
  case "$ExcludeDir" in
    /*) ;; # 絶対パスのまま
    *) ExcludeDir="${VideoRoot%/}/${ExcludeDir#./}" ;;
  esac

  if [ ! -d "$ExcludeDir" ]; then
    echo "Error: ${ExcludeDir} がディレクトリではありません" >&2
    exit 1
  fi
fi

# find の引数を配列で組み立て(ExcludeDir があれば -prune を追加)
find_args=( "$VideoRoot"/ )
if [ -n "$ExcludeDir" ]; then
  find_args+=( -path "$ExcludeDir" -prune -o )
fi
find_args+=( -type f -name "*rec*info*.txt" -print0 )

# find 実行 → null 区切りで読み込み
find "${find_args[@]}" |
  while IFS= read -r -d '' file; do
    # ファイル内にキーワードがあるかチェック
    if grep -qF -- "$KeyWord" "$file"; then
      # sed でキーワードを含む行をすべて削除(簡易エスケープ)
      escaped=$(printf '%s' "$KeyWord" | sed 's,[\/&],\\&,g')
      sed -i.bak "/$escaped/d" "$file"
      echo "[INFO] Removed lines matching '$KeyWord' from: $file"
    fi
  done

exit 0