Copiar carpeta recursivamente, excluyendo algunas carpetas

Estoy tratando de escribir un script bash simple que copiará todo el contenido de una carpeta, incluidos los archivos y carpetas ocultos en otra carpeta, pero quiero excluir ciertas carpetas específicas. ¿Cómo podría lograr esto?

Use rsync:

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

Tenga en cuenta que el uso de source y source/ son diferentes. Una barra inclinada significa copiar el contenido de la source de la carpeta al destination . Sin la barra al final, significa copiar el source la carpeta al destination .

Alternativamente, si tiene muchos directorios (o archivos) para excluir, puede usar --exclude-from=FILE , donde FILE es el nombre de un archivo que contiene archivos o directorios para excluir.

--exclude también puede contener comodines, como --exclude=*/.svn*

Use alquitrán junto con una tubería.

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

Incluso puedes usar esta técnica en ssh.

Puede usar find con la opción- -prune .

Un ejemplo del man find :

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

        Este comando copia los contenidos de / source-dir a / dest-dir, pero omite
        archivos y directorios llamados .snapshot (y cualquier cosa en ellos).  También
        omite archivos o directorios cuyo nombre termina en ~, pero no su
        carpas  La construcción -prune -o \ (... -print0 \) es bastante común.  los
        idea aquí es que la expresión antes de-run coincide con cosas que son
        para ser podado  Sin embargo, la acción de iniciación devuelve verdadera, por lo que
        El siguiente -o asegura que el lado derecho se evalúa solo para
        aquellos directorios que no se podaron (el contenido del podado
        los directorios ni siquiera son visitados, por lo que sus contenidos son irrelevantes).
        La expresión en el lado derecho de la -o está entre paréntesis
        para mayor claridad.  Hace hincapié en que la acción -print0 tiene lugar solo
        para cosas que no tenían -prune aplicado a ellos.  Porque el
        la condición `y 'predeterminada entre las pruebas se une más estrechamente que -o, esto
        es el valor predeterminado de todos modos, pero los paréntesis ayudan a mostrar lo que está pasando
        en.

Similar a la idea de Jeff (no probado):

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

puede usar tar, con la opción –exclude, y luego desatarlo en el destino. p.ej

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

ver la página man de tar para más información

 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 

No probado …

inspirado en la respuesta de @ SteveLazaridis, que fallará, aquí hay una función de shell POSIX: simplemente copie y pegue en un archivo llamado cpx en yout $PATH y haga que sea ejecutable ( chmod a+x cpr ). [La fuente ahora se mantiene en mi 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 "$@" 

Ejemplo de uso

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