J'essaie d'écrire un script bash simple qui va copier tout le contenu d'un dossier, y compris les fichiers et dossiers cachés, dans un autre dossier, mais je veux exclure certains dossiers spécifiques. Comment pourrais-je y parvenir?
Utilisez rsync:
rsync -av --exclude='path1/to/exclude' --exclude='path2/to/exclude' source destination
Notez que l'utilisation de source
et source/
est différente. Un slash de fin signifie copier le contenu du dossier source
dans destination
. Sans la barre oblique finale, cela signifie que vous copiez le dossier source
dans destination
.
Si vous devez exclure de nombreux répertoires (ou fichiers), vous pouvez également utiliser --exclude-from=FILE
, où FILE
est le nom d'un fichier contenant des fichiers ou des répertoires à exclure.
--exclude
peut également contenir des caractères génériques, tels que --exclude=*/.svn*
Utilisez du goudron avec un tuyau.
cd /source_directory
tar cf - --exclude=dir_to_exclude . | (cd /destination && tar xvf - )
Vous pouvez même utiliser cette technique sur ssh.
Vous pouvez utiliser find
avec l'option -Prune
.
Un exemple de man find
:
cd /source-dir trouver . -name .snapshot -Prune -o\(\! -name * ~ -print0 \) | cpio -pmd0 /dest-dir Cette commande copie le contenu de/source-dir dans/dest-dir, mais omet fichiers et répertoires nommés .snapshot (et tout ce qu’ils contiennent). Ça aussi omet les fichiers ou les répertoires dont le nom se termine par ~, mais pas leur con ‐ des tentes. La construction -Prune -o\(... -print0 \) est assez courante. Le L'idée ici est que l'expression avant -Prune correspond aux choses qui sont être élagué. Cependant, l'action -Prune elle-même retourne la valeur true, donc le En suivant -o, on s'assure que le côté droit est évalué uniquement pour les répertoires qui n'ont pas été élagués (le contenu des répertoires élagués n'est pas même visité, leur contenu est donc sans importance) . L'expression à droite du -o est entre parenthèses seulement pour plus de clarté. Il souligne que l'action -print0 n'a lieu que pour les choses qui n'ont pas -Prune appliqué à eux. Parce que le La condition par défaut `et 'entre les tests lie plus étroitement que -o, this est la valeur par défaut quand même, mais les parenthèses aident à montrer ce qui se passe sur.
Semblable à l'idée de Jeff (non testé):
find . -name * -print0 | grep -v "exclude" | xargs -0 -I {} cp -a {} destination/
vous pouvez utiliser tar avec l'option --exclude, puis le décompresser dans la destination. par exemple
cd /source_directory
tar cvf test.tar --exclude=dir_to_exclude *
mv test.tar /destination
cd /destination
tar xvf test.tar
voir la page de manuel de tar pour plus d'informations
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
Non testé ...
inspiré par la réponse de @ SteveLazaridis, qui échouerait, voici une fonction POSIX Shell - il suffit de copier et coller dans un fichier nommé cpx
in yout $PATH
et de le rendre exécutable (chmod a+x cpr
). [La source est maintenant conservée dans mon 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 "$@"
Exemple d'utilisation
EXCLUDE="
.git
my_secret_stuff
"
cpr "$HOME/my_stuff" "/media/usb" "$EXCLUDE"