Bash脚本无法移除字符串中的冒号问题求助
问题:Bash脚本中无法移除文件名里的冒号?
我编写了一个Bash脚本,开头设置了IFS=$'\n',随后用for i in *遍历文件,尝试通过${i//:/}移除文件名中的冒号,但无论用sed、tr还是其他字符串替换方法,冒号都无法被移除——其他字符都能正常处理,唯独冒号不行。
完整脚本如下:
#!/bin/bash IFS=$'\n' for i in *; do one=${i//:/} ###移除冒号 two=${one::-4} ###移除文件格式 three=${two,,} ###转为小写 four=${three// /-} ###空格替换为连字符 five=${four//\'} ###移除撇号 six=${five//.} ###移除句号 mkdir /home/"$whoami"/project/"$six" done IFS=$' \t\n'
解决方法
1. 先确认文件名的真实字符
你遇到的问题大概率是字符类型识别错误:比如文件名里的不是半角冒号:,而是全角冒号:(中文标点),或者是其他不可见的特殊字符。
先运行以下命令查看文件名的真实编码:
ls -b
-b参数会把特殊字符转义显示,比如全角冒号会显示为\346\226\207,这样就能明确要处理的字符到底是什么。
2. 修正遍历逻辑(核心修复)
IFS=$'\n'不会改变for i in *的通配符展开规则——通配符依然会按空格、制表符分割文件名,这会导致文件名被拆分,替换逻辑失效。改用find+while read的组合遍历更可靠:
#!/bin/bash # 用find遍历当前目录下的文件,避免通配符拆分问题 find . -maxdepth 1 -type f -print0 | while IFS= read -r -d '' i; do # 只提取文件名,避免路径字符干扰 filename=$(basename "$i") # 同时处理半角和全角冒号(根据实际情况调整) one=${filename//:/} one=${one//:/} # 后续字符处理逻辑保持不变 two=${one::-4} three=${two,,} four=${three// /-} five=${four//\'} six=${five//./} # 用$USER替代whoami,更可靠;加-p避免目录已存在报错 mkdir -p "/home/$USER/project/$six" done
3. 额外优化建议
- 替换
whoami为环境变量$USER,避免子进程调用的开销和潜在问题。 - 给
mkdir加-p参数,自动创建父目录且不会因目录已存在而报错。 - 如果文件名长度不足4位,
${one::-4}会报错,可以加判断:[[ ${#one} -ge 4 ]] && two=${one::-4} || two=$one。
内容的提问来源于stack exchange,提问作者MeepleDeMeep
相关产品推荐
相关产品推荐

