如何在Bash中忽略大小写检查列表中的文件是否存在
脚本优化:忽略大小写检查文件并处理复制
嘿,我看了你写的这个从输入文件提取格式字符串、忽略大小写检查文件存在性并复制的脚本,帮你梳理下问题和优化方案~
原脚本展示
for pattern in `grep -o [[:alnum:]]......-..-.. $inputfile | tr -d - | sed 's/./&./9' | tr '[A-Z]' '[a-z]'` do test -e $pattern || printf "Pattern $pattern is missing.\n" test -e $pattern && cp $pattern $dirname && printf "Pattern $pattern copied to $dirname\n" done
原脚本的几个问题
- 文件名拆分风险:用反引号
...配合for循环遍历输出时,如果提取的字符串里包含空格或特殊字符,会被循环拆分成多个元素,导致逻辑出错 - 大小写检查不彻底:你把提取的
pattern转成了小写,但test -e是严格匹配文件名大小写的——如果系统里的文件是大小写混合(比如Abc123.txt),脚本会误认为文件不存在 - 重复判断冗余:连续两次执行
test -e $pattern,做了重复的检查工作
优化后的脚本方案
这里提供两种兼容不同场景的优化版本:
方案1:用bash的大小写不敏感匹配(适合bash环境)
#!/bin/bash # 开启bash的大小写不敏感文件名匹配 shopt -s nocaseglob # 用while read安全读取提取的pattern,避免空格拆分问题 grep -o '[[:alnum:]]\{6\}-..-..' "$inputfile" | tr -d '-' | sed 's/./&./9' | tr '[A-Z]' '[a-z]' | while read -r pattern do # 利用nocaseglob特性匹配大小写不敏感的文件 matching_files=("$pattern") if [ ${#matching_files[@]} -eq 0 ] || [ ! -e "${matching_files[0]}" ]; then printf "Pattern %s is missing.\n" "$pattern" else cp "${matching_files[0]}" "$dirname" && printf "Pattern %s copied to %s\n" "$pattern" "$dirname" fi done # 关闭大小写不敏感匹配,避免影响后续脚本逻辑 shopt -u nocaseglob
方案2:用find命令跨shell兼容(适合非bash环境)
#!/bin/bash # 用while read安全遍历提取的pattern grep -o '[[:alnum:]]\{6\}-..-..' "$inputfile" | tr -d '-' | sed 's/./&./9' | tr '[A-Z]' '[a-z]' | while read -r pattern do # 用find的-iname参数忽略大小写查找,只取第一个匹配的文件 found_file=$(find . -maxdepth 1 -iname "$pattern" -type f -print -quit) if [ -z "$found_file" ]; then printf "Pattern %s is missing.\n" "$pattern" else cp "$found_file" "$dirname" && printf "Pattern %s copied to %s\n" "$pattern" "$dirname" fi done
优化点说明
- 安全遍历输出:用
while read -r代替for循环,避免文件名含空格/特殊字符时被错误拆分 - 真正忽略大小写检查:两种方案分别通过
nocaseglob或find -iname实现了忽略大小写的文件匹配,解决原脚本只能匹配小写文件的问题 - 减少冗余判断:合并了文件存在性的检查逻辑,避免重复执行
test -e - 变量安全引用:给所有变量加上双引号
",防止特殊字符导致的命令执行错误
内容的提问来源于stack exchange,提问作者Oleg Bukhantsov
相关产品推荐
相关产品推荐

