
Estoy intentando escribir un script para copiar archivos de forma recursiva desde una carpeta en particular, excepto archivos A.extn
, B/*.extn
y C/*
donde B
están C
los directorios y extn
es solo una extensión genérica. Esto es lo que tengo:
#!/usr/local/bin/zsh
setopt EXTENDED_GLOB
TMPDIR=/tmp/test
cp -pR $(dirname $0)/**~(*.foo/*|*/bar.txt|*.abc|qux.txt) $TMPDIR
Sin embargo, esto no niega el patrón como se esperaba. Creo que sé por qué: aunque el patrón es correcto (como se ve con echo
), cp -R
no es consciente del patrón e ingresa a un directorio que "se supone que no debe", y una vez allí, el patrón ya no es válido.
¿Cómo modifico lo anterior para hacer lo que quiero? Supongo que es posible con find
y xargs
, pero me atrae la claridad de lo anterior y preferiría algo similar (pero si es la forma incorrecta de hacerlo, estaría perfectamente feliz con una solución diferente).
Respuesta1
Tiene razón en que el patrón se expande antes de cp
ejecutarse, por lo que ese comando lo desconoce.
Es posible que pueda lograr lo que desea utilizando la --parents
opción en cp
lugar de -R
. Eso solo copiará los archivos que coincidan con su patrón, pero usará el nombre de ruta completo tal como se proporciona en lugar de solo el nombre del archivo final.
Pero esta opción no es portátil. AFAIK, solo es compatible con la versión GNU de cp.
Respuesta2
Su patrón puede excluir los archivos que no desea copiar, pero no excluye los directorios que los contienen y le indicó cp
que copiara de forma recursiva. Entonces los archivos se copian de todos modos. Peor que eso, si tienes un árbol fuente como
foo
foo/bar.txt
hello
hello/world
hello/world/wibble.txt
luego el patrón se expande para foo hello hello/world hello/world/wibble.txt
que termines con estos archivos en $TMPDIR
:
foo
foo/bar.txt
hello
hello/world
hello/world/wibble.txt
wibble.txt
world
world/wibble.txt
Esto no tiene nada que ver con que el patrón "ya no sea válido". El patrón se expande mediante el shell, cp
solo ve la lista de archivos.
Debe utilizar una herramienta de copia que pueda excluir archivos mientras realiza el recorrido recursivo.
Puede usar zcp para eso, pero no copiará los directorios y no creará directorios de destino automáticamente. La herramienta más sencilla para este trabajo es rsync. Pax es otra opción.
rsync -a --exclude='*.foo/*' --exclude='bar.txt' --exclude='*.abc' --exclude='/qux.txt' $(dirname $0) $TMPDIR