我试图写一个简单的bash脚本,将复制一个文件夹的全部内容,包括隐藏的文件和文件夹到另一个文件夹,但我想排除某些特定的文件夹。我怎么才能做到呢?
当前回答
使用焦油和管道。
cd /source_directory
tar cf - --exclude=dir_to_exclude . | (cd /destination && tar xvf - )
您甚至可以跨ssh使用此技术。
其他回答
受到@SteveLazaridis的答案的启发,这是一个POSIX shell函数-只需复制并粘贴到yout $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 -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 "$@"
示例使用
EXCLUDE="
.git
my_secret_stuff
"
cpr "$HOME/my_stuff" "/media/usb" "$EXCLUDE"
简单的解决方案(但我仍然更喜欢从顶部注释匹配bash模式):
touch /path/to/target/.git
cp -n -ax * /path/to/target/
rm /path/to/target/.git
这将利用cp的-n选项,强制cp不覆盖现有目标。
缺点:适用于GNU cp。如果您没有GNU cp,那么cp操作可能会返回一个错误代码(1),这很烦人,因为这样您就无法判断它是否是一个真正的失败。
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
未经考验的……
类似于Jeff的想法(未经测试):
find . -name * -print0 | grep -v "exclude" | xargs -0 -I {} cp -a {} destination/
你可以在-prune选项中使用find。
一个来自man find的例子:
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.