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?
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*
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.
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.
Ähnlich Jeffs Idee (ungeprüft):
find . -name * -print0 | grep -v "exclude" | xargs -0 -I {} cp -a {} destination/
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
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...
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"