如何让记录观影清单的Shell脚本在dmenu中正常运行?
问题描述
- 需求:通过dmenu运行脚本,将当前电影目录名追加到
watched.txt以记录已看电影 - 异常现象:终端运行脚本完全正常,但通过dmenu运行时,始终触发
else分支,提示"not inside movies directory" - 环境说明:
~/bin已加入$PATH,其他存放在该目录的脚本均可通过dmenu正常运行
用户提供的脚本代码:
#!/bin/sh parent_dir=$(basename "$(dirname "$PWD")") if [ "$parent_dir" = "movies" ];then choice=$(echo -e "yes\nno" | dmenu -p Watched?) if [ "$choice" = "yes" ];then echo "$(basename "$PWD")" >> /home/sinjini/movies/watched.txt && nl -s: -p ~/movies/watched.txt | dmenu -p "watched movies" -l 5 else nl -s: -p ~/movies/watched.txt | dmenu -p "watched movies" -l 5 fi else echo not inside movies directory | dmenu -p watched fi
问题根源
你的猜测完全正确:dmenu(以及绝大多数桌面环境启动的程序)的当前工作目录并非你打开dmenu时所在的终端目录,而是桌面环境的默认工作目录(通常是用户主目录~/)。因此脚本中$PWD在dmenu环境下指向的是~/,计算出的parent_dir自然不是"movies",直接触发了else分支。
解决方案
有两种可行的修正方向:
方向1:获取当前终端的工作目录
如果你的dmenu是从终端启动,或者需要关联当前终端的目录,可以借助xdotool读取终端进程的工作目录:
#!/bin/sh # 获取当前活跃终端的PID term_pid=$(xdotool getwindowfocus getwindowpid) # 读取该PID对应的工作目录 term_pwd=$(readlink /proc/$term_pid/cwd) # 计算父目录 parent_dir=$(basename "$(dirname "$term_pwd")") if [ "$parent_dir" = "movies" ];then choice=$(echo -e "yes\nno" | dmenu -p Watched?) if [ "$choice" = "yes" ];then echo "$(basename "$term_pwd")" >> /home/sinjini/movies/watched.txt && nl -s: -p ~/movies/watched.txt | dmenu -p "watched movies" -l 5 else nl -s: -p ~/movies/watched.txt | dmenu -p "watched movies" -l 5 fi else echo not inside movies directory | dmenu -p watched fi
注意:需要先安装xdotool(例如sudo apt install xdotool)。
方向2:让脚本接收目录参数
修改脚本,允许传入目标电影目录作为参数,脱离对当前工作目录的依赖:
#!/bin/sh # 检查是否传入目录参数 if [ -z "$1" ]; then echo "Usage: $0 <movie-directory>" | dmenu -p Error exit 1 fi # 验证目录合法性 if [ ! -d "$1" ]; then echo "Invalid directory" | dmenu -p Error exit 1 fi # 计算父目录 parent_dir=$(basename "$(dirname "$1")") if [ "$parent_dir" = "movies" ];then choice=$(echo -e "yes\nno" | dmenu -p Watched?) if [ "$choice" = "yes" ];then echo "$(basename "$1")" >> /home/sinjini/movies/watched.txt && nl -s: -p ~/movies/watched.txt | dmenu -p "watched movies" -l 5 else nl -s: -p ~/movies/watched.txt | dmenu -p "watched movies" -l 5 fi else echo not inside movies directory | dmenu -p watched fi
使用时,在终端执行watched "$PWD",或者将该命令绑定到快捷键,即可直接传递当前目录给脚本。
排查验证步骤
- 在脚本开头添加调试代码,查看dmenu环境下的
$PWD值:
运行后可确认dmenu的默认工作目录是否为用户主目录。echo "PWD is: $PWD" | dmenu -p Debug - 打印
parent_dir的值,验证计算逻辑:echo "parent_dir is: $parent_dir" | dmenu -p Debug
内容的提问来源于stack exchange,提问作者Sinjini
相关产品推荐
相关产品推荐

