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 lograrlo?

Author: trobrock, 2010-02-03

7 answers

Use rsync:

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

Tenga en cuenta que usar source y source/ son diferentes. Una barra diagonal significa copiar el contenido de la carpeta source en destination. Sin la barra final, significa copiar la carpeta source en 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*

 297
Author: Kaleb Pederson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-11 13:41:47

Use alquitrán junto con una tubería.

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

Incluso puede usar esta técnica a través de ssh.

 34
Author: Kyle Butt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-25 22:59:36

Puede usar find con la opción -prune.

Un ejemplo de 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.
 9
Author: Dennis Williamson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-03 18:53:18

Similar a la idea de Jeff (no probado):

find . -name * -print0 | grep -v "exclude" | xargs -0 -I {} cp -a {} destination/
 4
Author: Matthew Flaschen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-03 16:49:43

Puede usar tar, con la opción exclude exclude , y luego descomprimirlo en destino. eg

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

Vea la página de manual de tar para más información

 2
Author: ghostdog74,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-03 16:50:47
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

Probado...

 0
Author: Steve Lazaridis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-03 16:50:20

Inspirado por la respuesta de @SteveLazaridis, que fallaría, aquí hay una función de shell POSIX - simplemente copie y pegue en un archivo llamado cpx en yout $PATH y hágalo 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 -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 "$@"

Ejemplo de uso

EXCLUDE="
.git
my_secret_stuff
"
cpr "$HOME/my_stuff" "/media/usb" "$EXCLUDE"
 0
Author: go2null,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-27 16:48:29