unix 递归复制文件夹,不包括某些文件夹

r3i60tvu  于 2023-10-18  发布在  Unix
关注(0)|答案(9)|浏览(209)

我试图写一个简单的bash脚本,将复制到另一个文件夹,包括隐藏文件和文件夹的文件夹的全部内容,但我想排除某些特定的文件夹。我如何才能做到这一点?

of1yzvn4

of1yzvn41#

使用rsync:

rsync -av --exclude='path1/to/exclude' --exclude='path2/to/exclude' source destination

请注意,使用sourcesource/是不同的。结尾的斜杠表示将文件夹source的内容复制到destination中。如果没有结尾的斜杠,则表示将文件夹source复制到destination
或者,如果您有很多目录(或文件)要排除,您可以使用--exclude-from=FILE,其中FILE是包含要排除的文件或目录的文件的名称。
--exclude还可以包含通配符,例如--exclude=*/.svn*

px9o7tmv

px9o7tmv2#

用焦油沿着一个管道。

cd /source_directory
tar cf - --exclude=dir_to_exclude . | (cd /destination && tar xvf - )

你甚至可以在ssh中使用这种技术。

58wvjzkj

58wvjzkj3#

您可以将find-prune选项一起使用。
例如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.
egmofgnx

egmofgnx4#

快速入门

运行时间:

rsync -av --exclude='path1/in/source' --exclude='path2/in/source' [source]/ [destination]

备注

  • -avr将创建一个名为[destination]的新目录。
  • sourcesource/创建不同的结果:
  • source-将源的 * 内容 * 复制到目标。
  • source/-将 * 文件夹 * 源复制到目标。
  • 要排除多个文件,请执行以下操作:
  • --exclude-from=FILE-FILE是包含要排除的其他文件或目录的文件的名称。
  • --exclude也可以包含通配符:
  • 例如--exclude=*/.svn*

修改自:https://stackoverflow.com/a/2194500/749232

示例

开始文件夹结构:

.
├── destination
└── source
    ├── fileToCopy.rtf
    └── fileToExclude.rtf

运行时间:

rsync -av --exclude='fileToCopy.rtf' source/ destination

结束文件夹结构:

.
├── destination
│   └── fileToExclude.rtf
└── source
    ├── fileToCopy.rtf
    └── fileToExclude.rtf
bmp9r5qi

bmp9r5qi5#

你可以使用tar,带--exclude选项,然后在destination中解压缩它。eg

cd /source_directory
tar cvf test.tar --exclude=dir_to_exclude *
mv test.tar /destination 
cd /destination  
tar xvf test.tar

有关详细信息,请参阅tar的手册页

bihw5rsg

bihw5rsg6#

类似于Jeff的想法(未经测试):

find . -name * -print0 | grep -v "exclude" | xargs -0 -I {} cp -a {} destination/
4dbbbstv

4dbbbstv7#

简单的解决方案(但我仍然更喜欢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),这很烦人,因为这样您就无法判断这是否是一个真实的失败。

fhg3lkii

fhg3lkii8#

受@ SteveLazartik的回答的启发,这是一个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"
8hhllhi2

8hhllhi29#

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

未经测试的...

相关问题