在 Ubuntu(Linux)下,原生的 cp 命令本身没有方便的 --exclude 选项 ,要排除特定子目录,最常用且最推荐的做法是使用 rsync(几乎所有 Ubuntu 系统都预装了)。
假设你要:
- 源目录:
./src/ - 目标目录:
./dst/ - 要排除的两个子目录:
node_modules和.git
推荐写法(最常用、最清晰)
bash
# 方式1:推荐(使用相对路径排除)
rsync -a -i --exclude=node_modules --exclude=.git ./src/ ./dst/
# 方式2:更明确的写法(推荐在脚本中使用)
rsync -ai \
--exclude='node_modules' \
--exclude='.git' \
./src/ ./dst/
# 方式3:如果排除的目录比较多,可以用排除文件
cat > exclude.txt << 'EOF'
node_modules/
.git/
EOF
rsync -ai --exclude-from=exclude.txt ./src/ ./dst/
参数说明
| 选项 | 含义 |
|---|---|
-a |
归档模式(保留权限、时间、符号链接等)≈ -rlptgoD |
-i / --itemize-changes |
显示哪些文件被拷贝(类似你用的 -r 时的交互感,但更详细) |
--exclude |
排除匹配的路径(从源目录算起的相对路径) |
末尾的 / |
非常重要!表示拷贝 src 目录里面的内容,而不是拷贝 src 这个目录本身 |
如果你非常坚持只用 cp(不推荐)
方法一:使用 bash 的 extglob(比较麻烦)
bash
# 先开启 extglob 功能
shopt -s extglob
# 拷贝所有东西,除了 node_modules 和 .git 两个目录
cp -air ./src/!(node_modules|.git) ./dst/
方法二:使用 find + cp(更可靠但更慢)
bash
find ./src/ \
-mindepth 1 \
-not -path "./src/node_modules/*" \
-not -path "./src/.git/*" \
-not -name node_modules \
-not -name .git \
-exec cp -air {} ./dst/ \;
总结推荐顺序(从好到差):
rsync -ai --exclude=xxx --exclude=yyy src/ dst/← 最推荐rsync -ai --exclude-from=exclude.txt src/ dst/- bash extglob 的
cp -air src/!(dir1|dir2) dst/ - find + cp 的组合(最灵活但最慢)