如何在Bash中结合-exec使用cat命令?脚本生成异常文件问题
问题原因
这个坑我之前踩过!核心问题是shell重定向的解析时机不对:当你在find的-exec里直接写cat /home/new/$1 > {}时,外层shell会先处理重定向操作——也就是在find开始执行之前,就把>后面的{}当成了当前目录下的普通文件名,所以cat的输出直接写到了脚本所在目录的{}文件里,完全没让find去替换这个占位符。
修正后的脚本
最简单的修复方式是用sh -c启动一个子shell,让重定向在子shell内部完成,这样find的占位符就能被正确替换:
#!/bin/bash find /home/old -path "*$1" -exec sh -c 'cat /home/new/"$1" > "$0"' {} "$1" \;
如果要更健壮(比如检查新文件是否存在、避免空内容覆盖、处理特殊字符),可以升级成这样:
#!/bin/bash # 先检查用户是否传入了文件名参数 if [ -z "$1" ]; then echo "用法:$0 <要替换的文件名>" >&2 exit 1 fi target_filename="$1" find /home/old -path "*${target_filename}" -exec sh -c ' new_file="/home/new/$1" # 先确认新文件存在,避免把空内容写入目标文件 if [ -f "$new_file" ]; then cat "$new_file" > "$0" echo "已更新:$0" else echo "警告:新文件 $new_file 不存在,跳过 $0" >&2 fi ' {} "${target_filename}" \;
关键原理解释
find的-exec后面的sh -c '...' {} "$1"中:{}会被find替换成匹配到的目标文件路径,作为子shell的$0"$1"是我们脚本接收的文件名参数,作为子shell的$1
- 子shell内部的重定向
> "$0"是在find替换完占位符之后才处理的,所以会正确写入到目标文件中,而不是当前目录的{}。
额外小建议
- 如果你只是想匹配文件名(而不是路径中包含该字符串),把
-path "*$1"改成-name "$1"会更准确,避免误匹配路径里包含该字符串的其他文件。 - 如果你的文件名包含空格、引号等特殊字符,当前写法用双引号包裹了所有变量,能安全处理这些情况。
内容的提问来源于stack exchange,提问作者Dobi Caps
相关产品推荐
相关产品推荐

