使用系统内置命令复制文件/目录时,如何正确排除多个指定的文件和目录
使用系统内置命令复制文件/目录时,如何正确排除多个指定的文件和目录
我看了你的问题,原来的find命令逻辑出了点小问题,导致不该复制的文件和目录混进来了。咱们先拆解下问题,再给出靠谱的解决方案。
首先,你要排除的目标很明确:
- 两个目录:
/opt/share/555/666、/opt/share/555/888/8881 - 一个文件:
/opt/share/555/test.txt
原来命令的问题所在
你之前的命令里,-prune只和最后的-path /opt/share/555/test.txt绑定了,而前面要排除的目录没有和-prune结合。这就导致find还是会遍历到一些不该处理的内容——比如777/71.sh被单独复制出来,888/8881也没被跳过,本质是-prune的作用范围没覆盖到所有要排除的项。
正确的find命令写法
咱们调整下find的逻辑,让-prune正确作用于每个要排除的项:
find /opt/share/555/ -mindepth 1 \ \( -type d \( -path "/opt/share/555/666" -o -path "/opt/share/555/888/8881" \) -prune \) \ -o \( -type f -path "/opt/share/555/test.txt" -prune \) \ -o -exec cp -prf {} /opt/share/2/ \;
命令逻辑解释:
- 第一部分:匹配到你要排除的两个目录,用
-prune跳过它们——既不会进入这些目录遍历内容,也不会复制这些目录本身。 - 第二部分:匹配到你要排除的
test.txt文件,同样用-prune跳过,不执行后续的复制操作。 - 最后一部分:所有没被前面规则排除的文件和目录,执行
cp -prf命令复制到目标路径。
执行这个命令后,/opt/share/2/的目录结构就会符合你的预期:只有777(包含里面的71.sh)、888(不含8881)、test2.sh、test.sh,不会出现单独的71.sh和不该有的8881目录。
备选方案:先复制再删除
如果觉得find的逻辑有点绕,也可以用更直白的方式:先把所有内容复制过去,再删掉不需要的项。这种方法适合源目录不大的情况:
# 先完整复制所有内容 cp -prf /opt/share/555/* /opt/share/2/ # 删掉要排除的目录和文件 rm -rf /opt/share/2/666 rm -rf /opt/share/2/888/8881 rm -f /opt/share/2/test.txt
不过这种方法的缺点是如果源目录很大,复制过程会浪费时间,而且如果有文件正在被写入,可能会出现不一致的情况,所以优先推荐第一种find的方案。
备注:内容来源于stack exchange,提问作者Lillian Gordon
相关产品推荐
相关产品推荐

