如何在Bash脚本中无错误地使用detox清理文件名?
如何在Bash脚本中无错误地使用detox清理文件名?
先明确下我们的测试环境:
- OS: Kubuntu 22.04.4 LTS x86_64
- detox版本:1.4.5
你可以用这两条命令快速确认环境信息:
neofetch --stdout |grep 'OS:' detox -V
我们用这个满是特殊字符的「有毒」文件名做测试:
s1 Ä Ö Ü - ä ö ü Science & < > " 1 \ 2 ⁄ 3 | ? * (&&9&&&) ::::z.pdf
先看能正常工作的脚本(Script1)
Script1里我们直接指定了目标文件名,用detox处理完全没问题,最终能得到干净的文件名:s1_A_A-Aoe-A_A_pp_A_Science_and_1_2_a_3-and_and_9_and_and_and-z.pdf
Script1代码如下:
clear DIR1=$HOME/Downloads # DIR1=/home/x/Downloads cd $DIR1 ls -alF s1* # 列出所有以s1开头的文件 FILE1='s1 Ä Ö Ü - ä ö ü Science & < > " 1 \ 2 ⁄ 3 | ? * (&&9&&&) ::::z.pdf' detox -s iso8859_1 "$FILE1" # detox -s iso8859_1 -v "$FILE1" # 加上-v可以查看详细处理过程 ls -alF s1* # 再次列出文件,确认处理结果
问题出在自动监控的Script2
你想用inotifywait监控下载目录,自动处理新文件,但执行时弹出一堆No such file or directory错误——虽然最终文件名能被正确清理,但这些错误信息实在闹心。
原Script2代码:
clear DIR1=$HOME/Downloads # DIR1=/home/x/Downloads inotifywait -q -m -e close_write,moved_to --format '%w%f' "$DIR1" |while read FILE1 do ls -alF s1* # 列出所有以s1开头的文件 detox -s iso8859_1 ""$FILE1"" ls -alF s1* # 再次列出文件 done
你遇到的错误大概是这样的:
rw-rw-r-- 1 x x 1153263 Mar 13 11:36 's1 Ä Ö Ü - ä ö ü Science & < > " 1 \ 2 ⁄ 3 | ? * (&&9&&&) ::::z.pdf' /home/x/Downloads/s1: No such file or directory Ä: No such file or directory Ö: No such file or directory ...(一堆类似的错误提示) -rw-rw-r-- 1 x x 1153263 Mar 13 11:36 s1_A_A-Aoe-A_A_pp_A_Science_and_1_2_a_3-and_and_9_and_and_and-z.pdf
为啥会出错?
核心问题在文件名的读取和参数传递上:
- 默认的
read命令会把输入按空格拆分,当文件名里有空格、特殊字符时,FILE1会被拆成一堆零散的字符串,detox会把这些拆分后的内容当成单独的文件名,自然找不到对应的文件,就报错了。 - 你用的
""$FILE1""这种写法完全是画蛇添足,反而破坏了双引号的作用,让特殊字符暴露给shell解析,导致更多问题。
修复后的Script2(无错误版)
我们只需要调整read的行为,同时正确使用引号包裹变量,再加上文件存在检查,就能彻底解决错误:
clear DIR1=$HOME/Downloads # DIR1=/home/x/Downloads inotifywait -q -m -e close_write,moved_to --format '%w%f' "$DIR1" | while IFS= read -r FILE1 do ls -alF s1* # 列出所有以s1开头的文件 # 先确认是文件再处理,避免误处理目录或非文件事件 if [ -f "$FILE1" ]; then detox -s iso8859_1 "$FILE1" fi ls -alF s1* # 查看处理结果 done
关键修改点解释:
IFS= read -r FILE1:IFS=保留输入的开头和结尾空格,防止文件名里的空格被截断-r禁止反斜杠转义,保证文件名里的反斜杠被正确读取,不会被当成转义字符处理
"$FILE1":用双引号完整包裹变量,确保shell把整个文件名当成一个参数传递给detox,不会拆分特殊字符- 文件存在检查:
if [ -f "$FILE1" ]; then,避免inotifywait触发目录变化等非文件事件时执行detox,减少不必要的错误
补充下工具的作用
关于detox
detox就是用来清理文件名的工具,把那些带空格、特殊字符、非ASCII字符的文件名改成更友好的格式- 它支持转换ISO 8859-1、UTF-8编码的特殊字符,还能处理CGI转义字符,彻底去掉文件名里的「麻烦元素」
关于inotifywait
inotifywait是Linux下监控文件系统变化的实用工具,基于内核的inotify接口- 它能高效等待文件的创建、修改、移动等事件,非常适合写自动处理脚本
- 可以持续监控并输出事件,也可以触发一次就退出
备注:内容来源于stack exchange,提问作者joseph22
相关产品推荐
相关产品推荐

