You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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}" \;
关键原理解释
  1. find的-exec后面的sh -c '...' {} "$1"中:
    • {}会被find替换成匹配到的目标文件路径,作为子shell的$0
    • "$1"是我们脚本接收的文件名参数,作为子shell的$1
  2. 子shell内部的重定向> "$0"是在find替换完占位符之后才处理的,所以会正确写入到目标文件中,而不是当前目录的{}。
额外小建议
  • 如果你只是想匹配文件名(而不是路径中包含该字符串),把-path "*$1"改成-name "$1"会更准确,避免误匹配路径里包含该字符串的其他文件。
  • 如果你的文件名包含空格、引号等特殊字符,当前写法用双引号包裹了所有变量,能安全处理这些情况。

内容的提问来源于stack exchange,提问作者Dobi Caps

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:25:16