recursion复制文件夹,排除一些文件夹
我想写一个简单的bash脚本,将包括隐藏的文件和文件夹的文件夹的全部内容复制到另一个文件夹,但我想排除某些特定的文件夹。 我怎么能做到这一点?
使用rsync:
rsync -av --exclude='path1/to/exclude' --exclude='path2/to/exclude' source destination
请注意,使用source
和source/
是不同的。 尾部斜线表示将文件夹source
的内容复制到destination
。 没有结尾斜杠,这意味着将文件夹source
复制到destination
。
或者,如果要排除很多目录(或文件),则可以使用--exclude-from=FILE
,其中FILE
是包含要排除的文件或目录的文件的名称。
--exclude
也可能包含通配符,比如--exclude=*/.svn*
使用tar和一个pipe道。
cd /source_directory tar cf - --exclude=dir_to_exclude . | (cd /destination && tar xvf - )
你甚至可以通过SSH使用这种技术。
您可以使用-prune
选项来find
。
从man find
一个例子man find
:
cd / source-dir 找 。 -name .snapshot -prune -o \(\!-name *〜-print0 \)| cpio -pmd0 / dest-dir 该命令将/ source-dir的内容复制到/ dest-dir,但省略 名为.snapshot的文件和目录(以及其中的任何内容)。 它也是 省略名称以〜结尾的文件或目录,但不包含其结尾 帐篷。 构造-prune -o \(... -print0 \)是相当普遍的。 该 这里的想法是-prune之前的expression匹配的东西是 被修剪。 然而,-prune动作本身返回true,所以 以下-o确保只评估右侧 那些没有被修剪的目录(修剪过的内容) 目录甚至没有访问,所以他们的内容是无关的)。 -o的右侧expression式仅在括号内 为清楚起见。 它强调只有-print0动作发生 对于那些没有应用的东西。 因为 默认`和`testing之间的条件绑定比-o更紧密,这 无论如何是默认的,但括号有助于显示发生了什么 上。
类似杰夫的想法(未经testing):
find . -name * -print0 | grep -v "exclude" | xargs -0 -I {} cp -a {} destination/
你可以使用tar和–exclude选项,然后解压到目的地。 例如
cd /source_directory tar cvf test.tar --exclude=dir_to_exclude * mv test.tar /destination cd /destination tar xvf test.tar
有关更多信息,请参阅tar的手册页
EXCLUDE="foo bar blah jah" DEST=$1 for i in * do for x in $EXCLUDE do if [ $x != $i ]; then cp -a $i $DEST fi done done
未经testing…
启发@ SteveLazaridis的答案,这将失败,这是一个POSIX shell函数 – 只需复制并粘贴到$PATH
的文件名为cpx
,并使其可执行( chmod a+x cpr
)。 [源现在保存在我的GitLab中 。
#!/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 -rf; 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 "$@"
用法示例
EXCLUDE=" .git my_secret_stuff " cpr "$HOME/my_stuff" "/media/usb" "$EXCLUDE"