linux - uso - ¿Cómo usar el comando ''cp'' para excluir un directorio específico?
uso cp linux (17)
Quiero copiar todos los archivos en un directorio, excepto algunos archivos en un subdirectorio específico. Me he dado cuenta de que el comando ''cp'' no tenía una opción --exclude. Entonces, ¿cómo puedo lograr esto?
Ampliando el comentario de mvds , esto funciona para mí.
cd dotfiles
tar -c --exclude .git --exclude README . | tar -x -C ~/dotfiles2
Bueno, si la exclusión de ciertos patrones de nombre de archivo tuviera que ser realizada por cada utilidad de archivo unix-ish (como cp, mv, rm, tar, rsync, scp, ...), se produciría una inmensa duplicación de esfuerzos. En su lugar, estas cosas se pueden hacer como parte de un globbing , es decir, por su shell.
golpetazo
Link a manual, búsqueda de extglob .
Ejemplo:
$ shopt -s extglob $ echo images/* images/004.bmp images/033.jpg images/1276338351183.jpg images/2252.png $ echo images/!(*.jpg) images/004.bmp images/2252.png
Así que solo pones un patrón dentro !()
, y niega la coincidencia. El patrón puede ser arbitrariamente complejo, comenzando desde la enumeración de rutas individuales (como lo muestra Vanwaril en otra respuesta) !(filename1|path2|etc3)
, a cosas similares a !(filename1|path2|etc3)
regulares con estrellas y clases de caracteres. Consulte la página del manual para más detalles.
zsh
Link al manual, sección "generación de nombre de archivo" .
Puedes hacer setopt KSH_GLOB
y usar patrones tipo bash. O,
% setopt EXTENDED_GLOB % echo images/* images/004.bmp images/033.jpg images/1276338351183.jpg images/2252.png % echo images/*~*.jpg images/004.bmp images/2252.png
Entonces x~y
coincide con el patrón x
, pero excluye el patrón y
. Una vez más, para más detalles consulte la página del manual.
pescado nuevo!
La cáscara de fish tiene una respuesta mucho más bonita a esto:
🐟 cp (string match -v ''*.excluded.names'' -- srcdir/*) destdir
Bonus pro-tip
Escriba cp *
, presione Ctrl X * y solo vea lo que sucede. no es perjudicial lo prometo
Es relativo al directorio de origen.
Esto excluirá la source/.git
del directorio source/.git
de copiarse.
rsync -r --exclude ''.git'' source target
Esta es una modificación de la respuesta de Linus Kleen. Su respuesta no funcionó para mí porque habría un. añadido delante de la ruta del archivo que no le gusta a cp (la ruta se vería como source / .destination / file).
Este comando funcionó para mí:
find . -type f -not -path ''*/exlude-path/*'' -exec cp --parents ''{}'' ''/destination/'' /;
El comando --parents conserva la estructura del directorio.
La forma más fácil que encontré, donde puede copiar todos los archivos excluyendo archivos y carpetas simplemente agregando sus nombres entre paréntesis:
shopt -s extglob
cp -r !(Filename1 | FoldernameX | Filename2) Dest/
Otra opción más simple es instalar y usar rsync que tiene una opción --exclude-dir, y puede usarse tanto para archivos locales como remotos.
Por qué usar rsync
cuando puedes hacer:
find . -type f -not -iname ''*/not-from-here/*'' -exec cp ''{}'' ''/dest/{}'' '';''
Esto supone que la estructura del directorio de destino es la misma que la de la fuente.
Simplemente muévalo temporalmente a un directorio oculto (y cámbiele el nombre después, si lo desea).
mkdir .hiddendir
cp * .hiddendir -R
mv .hiddendir realdirname
Supongo que estás usando bash o dash. ¿Funcionaría esto?
shopt -s extglob # sets extended pattern matching options in the bash shell
cp $(ls -laR !(subdir/file1|file2|subdir2/file3)) destination
Haciendo un ls excluyendo los archivos que no desea, y usándolo como el primer argumento para cp
Una forma sería usar find -0
con -prune
para encontrar todos los archivos y directorios que desea mover, luego use xargs -0
para copiar cada uno.
Utilizo un bucle "hacer mientras que" para leer la salida del comando de búsqueda. En este ejemplo, estoy haciendo coincidir (en lugar de excluir) ciertos patrones, ya que hay un número más limitado de coincidencias de patrones que deseo que no quiero. Podría revertir la lógica con un -no delante de las banderas -iname:
find . -type f -iname "*.flac" -o -print0 -iname "*.mp3" -print0 -o -iname "*.wav" -print0 -o -iname "*.aac" -print0 -o -iname "*.wma" -print0 | while read -d $''/0'' file; do cp -ruv "$file" "/media/wd/network_sync/music/$file"; done
Uso lo anterior para copiar todos los archivos de tipo de música que son más nuevos en mi servidor que los archivos en un Live Hub de Western Digital TV que he montado en / media / wd. Uso lo anterior porque tengo muchos archivos de DVD, mpegs, etc. que quiero excluir Y porque por alguna razón parece que rsync está copiando, pero después de mirar el dispositivo wd, los archivos no están allí a pesar de que no errores durante el rsync con este comando:
rsync -av --progress --exclude=*.VOB --exclude=*.avi --exclude=*.mkv --exclude=*.ts --exclude=*.mpg --exclude=*.iso --exclude=*ar --exclude=*.vob --exclude=*.BUP --exclude=*.cdi --exclude=*.ISO --exclude=*.shn --exclude=*.MPG --exclude=*.AVI --exclude=*.DAT --exclude=*.img --exclude=*.nrg --exclude=*.cdr --exclude=*.bin --exclude=*.MOV --exclude=*.goutputs* --exclude=*.flv --exclude=*.mov --exclude=*.m2ts --exclude=*.cdg --exclude=*.IFO --exclude=*.asf --exclude=*.ite /media/2TB/ Data/data/music/* /media/wd/network_sync/music/
rsync
rsync -r --verbose --exclude ''exclude_pattern'' ./* /to/where/
y primero inténtelo con la opción -n para ver qué se va a copiar
rsync es rápido y fácil:
rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude
Puedes usar --exclude
multiples veces.
También puede agregar -n
para la ejecución en seco para ver qué se copiará antes de realizar una operación real, y si todo está bien, elimine -n
de la línea de comandos.
rsync
es en realidad bastante complicado. Hay que hacer varias pruebas para que funcione.
Digamos que desea copiar /var/www/html
a /var/www/dev
pero necesita excluir /var/www/html/site/video/
directory tal vez debido a su tamaño. El comando sería:
rsync -av --exclude ''sites/video'' /var/www/html/ /var/www/dev
Algunas advertencias :
- La última barra diagonal
/
en la fuente es necesaria, de lo contrario también copiará el directorio fuente en lugar de su contenido y se convertirá en/var/www/dev/html/xxxx
, que tal vez no sea lo que desea. La ruta
--exclude
es relativa a la fuente directamente. Incluso si pones la ruta absoluta completa, no funcionará.-v
es para verbose,-a
es para el modo de archivo, lo que significa que desea recursión y desea conservar casi todo.
cp -r `ls -A | grep -v "c"` $HOME/
cp -rv `ls -A | grep -vE "dirToExclude|targetDir"` targetDir
Edición: también se olvidó de excluir la ruta de destino (de lo contrario, se copiaría de forma recursiva).
mv tobecopied/tobeexcluded .
cp -r tobecopied dest/
mv tobeexcluded tobecopied/