Bash脚本实现通配符(*)支持以完成文件/文件夹的复制与删除
解决方案:同时兼容带空格路径与通配符
方法1:拆分目录与通配符模式(最安全)
核心思路是把带通配符的路径拆分为目录部分和匹配模式,分别处理后再拼接,既保留空格,又让通配符正常展开。
代码示例
假设你的脚本从CSV读取source和dest路径,修改如下:
# 启用nullglob:通配符无匹配时返回空数组,避免传递原字符串导致错误 shopt -s nullglob while IFS=, read -r source dest; do # 拆分目录和匹配模式 dir_path=$(dirname "$source") pattern=$(basename "$source") # 拼接路径并展开通配符,存入数组 matched_files=("$dir_path"/"$pattern") # 检查是否有匹配项 if [ ${#matched_files[@]} -eq 0 ]; then echo "警告:无匹配文件/目录: $source" >&2 continue fi # 执行复制/删除操作(这里以cp为例,rm同理) cp -r "${matched_files[@]}" "$dest" done < your_config.csv # 关闭nullglob(可选,恢复Bash默认行为) shopt -u nullglob
优点
- 完全避免
eval带来的安全风险,适合处理不可信的CSV输入 - 天然支持带空格的路径和通配符(
*、?、[]等) - 可通过
globstar选项扩展支持递归通配符**(只需在shopt -s后添加globstar)
方法2:使用eval快速实现(仅适用于可信输入)
如果你的CSV配置文件是完全可信的(无恶意内容),可以用eval直接展开通配符,同时保留带空格的路径。
代码示例
while IFS=, read -r source dest; do # 用eval展开通配符并赋值给数组 eval "matched_files=($source)" if [ ${#matched_files[@]} -eq 0 ]; then echo "警告:无匹配文件/目录: $source" >&2 continue fi cp -r "${matched_files[@]}" "$dest" done < your_config.csv
注意事项
- 风险提示:如果CSV中包含
;、&、$()等特殊字符,eval会执行恶意命令,仅在输入完全可信时使用 - 同样可以配合
nullglob优化无匹配时的行为
方法3:用find替代通配符(适合复杂匹配)
如果需要更复杂的文件匹配逻辑(比如按时间、类型筛选),可以用find命令遍历目录,天然支持带空格的路径。
代码示例(实现dir/*的效果)
while IFS=, read -r source dest; do # 提取目录部分(去掉末尾的/*) dir_path=$(echo "$source" | sed 's/\/\*$//') # 检查目录是否存在 if [ ! -d "$dir_path" ]; then echo "错误:目录不存在: $dir_path" >&2 continue fi # 遍历目录下所有内容(不递归),执行复制 find "$dir_path" -maxdepth 1 -mindepth 1 -exec cp -r {} "$dest" \; done < your_config.csv
优点
- 支持更灵活的筛选条件(比如
-type f仅复制文件,-mtime -7复制7天内的文件) - 完全避免通配符展开的问题,适合复杂场景
关键原理说明
Bash中,引号会抑制通配符展开,但空格需要引号/转义才能被当作路径的一部分。上述方法通过拆分路径、数组存储或外部命令的方式,同时满足两个需求:
- 带空格的路径被当作单个整体处理
- 通配符被正常展开为匹配的文件/目录
内容的提问来源于stack exchange,提问作者phramusca
相关产品推荐
相关产品推荐

