cd /source-dir
find . -name .snapshot -prune -o \( \! -name *~ -print0 \)|
cpio -pmd0 /dest-dir
This command copies the contents of /source-dir to /dest-dir, but omits
files and directories named .snapshot (and anything in them). It also
omits files or directories whose name ends in ~, but not their con‐
tents. The construct -prune -o \( ... -print0 \) is quite common. The
idea here is that the expression before -prune matches things which are
to be pruned. However, the -prune action itself returns true, so the
following -o ensures that the right hand side is evaluated only for
those directories which didn't get pruned (the contents of the pruned
directories are not even visited, so their contents are irrelevant).
The expression on the right hand side of the -o is in parentheses only
for clarity. It emphasises that the -print0 action takes place only
for things that didn't have -prune applied to them. Because the
default `and' condition between tests binds more tightly than -o, this
is the default anyway, but the parentheses help to show what is going
on.
#!/bin/sh
# usage: cpx [-n|--dry-run] "from_path" "to_path" "newline_separated_exclude_list"
# limitations: only excludes from "from_path", not it's subdirectories
cpx() {
# run in subshell to avoid collisions
(_CopyWithExclude "$@")
}
_CopyWithExclude() {
case "$1" in
-n|--dry-run) { DryRun='echo'; shift; } ;;
esac
from="$1"
to="$2"
exclude="$3"
$DryRun mkdir -p "$to"
if [ -z "$exclude" ]; then
cp "$from" "$to"
return
fi
ls -A1 "$from" \
| while IFS= read -r f; do
unset excluded
if [ -n "$exclude" ]; then
for x in $(printf "$exclude"); do
if [ "$f" = "$x" ]; then
excluded=1
break
fi
done
fi
f="${f#$from/}"
if [ -z "$excluded" ]; then
$DryRun cp -R "$f" "$to"
else
[ -n "$DryRun" ] && echo "skip '$f'"
fi
done
}
# Do not execute if being sourced
[ "${0#*cpx}" != "$0" ] && cpx "$@"
9条答案
按热度按时间of1yzvn41#
使用rsync:
请注意,使用
source
和source/
是不同的。结尾的斜杠表示将文件夹source
的内容复制到destination
中。如果没有结尾的斜杠,则表示将文件夹source
复制到destination
。或者,如果您有很多目录(或文件)要排除,您可以使用
--exclude-from=FILE
,其中FILE
是包含要排除的文件或目录的文件的名称。--exclude
还可以包含通配符,例如--exclude=*/.svn*
px9o7tmv2#
用焦油沿着一个管道。
你甚至可以在ssh中使用这种技术。
58wvjzkj3#
您可以将
find
与-prune
选项一起使用。例如
man find
:egmofgnx4#
快速入门
运行时间:
备注
-avr
将创建一个名为[destination]
的新目录。source
和source/
创建不同的结果:source
-将源的 * 内容 * 复制到目标。source/
-将 * 文件夹 * 源复制到目标。--exclude-from=FILE
-FILE
是包含要排除的其他文件或目录的文件的名称。--exclude
也可以包含通配符:--exclude=*/.svn*
修改自:https://stackoverflow.com/a/2194500/749232
示例
开始文件夹结构:
运行时间:
结束文件夹结构:
bmp9r5qi5#
你可以使用tar,带--exclude选项,然后在destination中解压缩它。eg
有关详细信息,请参阅tar的手册页
bihw5rsg6#
类似于Jeff的想法(未经测试):
4dbbbstv7#
简单的解决方案(但我仍然更喜欢bash模式匹配顶部的评论):
这利用了
cp
的-n
选项,该选项强制cp
不覆盖现有目标。缺点:适用于GNU
cp
。如果您没有GNUcp
,那么cp
操作可能会返回一个错误代码(1
),这很烦人,因为这样您就无法判断这是否是一个真实的失败。fhg3lkii8#
受@ SteveLazartik的回答的启发,这是一个POSIX shell函数-只需复制并粘贴到yout
$PATH
中名为cpx
的文件中,并使其可执行(chmod a+x cpr
)。[源代码现在维护在我的GitLab中。示例使用
8hhllhi29#
未经测试的...