it-swarm.com.de

Ordner rekursiv kopieren, ausgenommen einige Ordner

Ich versuche, ein einfaches Bash-Skript zu schreiben, das den gesamten Inhalt eines Ordners einschließlich versteckter Dateien und Ordner in einen anderen Ordner kopiert. Ich möchte jedoch bestimmte Ordner ausschließen. Wie kann ich das erreichen?

180
trobrock

Verwenden Sie Rsync:

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

Beachten Sie, dass sich source und source/ unterscheiden. Ein nachstehender Schrägstrich bedeutet, den Inhalt des Ordners source in destination zu kopieren. Ohne den abschließenden Schrägstrich muss der Ordner source in destination kopiert werden.

Wenn Sie viele Verzeichnisse (oder Dateien) ausschließen möchten, können Sie alternativ --exclude-from=FILE verwenden, wobei FILE der Name einer Datei ist, die Dateien oder Verzeichnisse enthält, die ausgeschlossen werden sollen.

--exclude kann auch Platzhalterzeichen enthalten, z. B. --exclude=*/.svn*

302
Kaleb Pederson

Verwenden Sie Teer zusammen mit einer Pfeife.

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

Sie können diese Technik sogar für ssh verwenden.

36
Kyle Butt

Sie können find mit der Option -Prune verwenden.

Ein Beispiel aus man find:

 cd /source-dir
 finden . -name .snapshot -Prune -o\(\! -name * ~ -print0 \) | 
 cpio -pmd0 /dest-dir

 Dieser Befehl kopiert den Inhalt von/source-dir nach/dest-dir, lässt jedoch .__ aus. Dateien und Verzeichnisse mit dem Namen .snapshot (und alle darin enthaltenen Elemente). Es auch 
 lässt keine Dateien oder Verzeichnisse aus, deren Name auf ~ endet, jedoch nicht deren con ‐
 Zelte Das Konstrukt -Prune -o\(... -print0 \) kommt häufig vor. Das
 Die Idee hier ist, dass der Ausdruck vor -Prune mit Dingen übereinstimmt, die .__ sind. beschnitten werden Die -Prune-Aktion selbst gibt jedoch true zurück, also die 
 Folgendes -o stellt sicher, dass die rechte Seite nur für .__ ausgewertet wird. die Verzeichnisse, die nicht gelöscht wurden (der Inhalt der beschnittenen 
 -Verzeichnisse wird nicht einmal besucht, daher ist ihr Inhalt nicht relevant) .
 Der Ausdruck auf der rechten Seite von -o steht nur in Klammern 
 zur Klarheit. Es wird betont, dass die Aktion -print0 nur .__ stattfindet. für Dinge, für die -Prune nicht gilt. Weil der
 Die standardmäßige `und 'Bedingung zwischen den Tests bindet enger als -o, diese 
 ist der Standardwert, aber die Klammern zeigen an, was gerade läuft 
 auf.
9

Ähnlich Jeffs Idee (ungeprüft):

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

sie können tar mit der Option --exclude verwenden und die Freigabe dann im Ziel aufheben. z.B

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

weitere Informationen finden Sie auf der Man-Seite von tar

2
ghostdog74
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

Ungetestet...

0
Steve Lazaridis

inspiriert von der Antwort von @ SteveLazaridis, die fehlschlagen würde, ist hier eine POSIX-Shell-Funktion - einfach kopieren und in eine Datei mit dem Namen cpx in yout $PATH einfügen und ausführbar machen (chmod a+x cpr). [Source wird jetzt in meinem GitLab gepflegt.

#!/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 "[email protected]")
}

_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 "[email protected]"

Verwendungsbeispiel

EXCLUDE="
.git
my_secret_stuff
"
cpr "$HOME/my_stuff" "/media/usb" "$EXCLUDE"
0
go2null