Digamos que quiero copiar el contenido de un directorio excluyendo archivos y carpetas cuyos nombres contienen la palabra 'Música'.
cp [exclude-matches] *Music* /target_directory
¿Qué debería ir en lugar de [excluir-coincidencias] para lograr esto?
bash
shell
pattern-matching
glob
usuario4812
fuente
fuente

ls /dir/*/!(base*)f, exceptofoo?La
extglobopción de shell le ofrece una coincidencia de patrones más potente en la línea de comandos.Lo enciendes
shopt -s extgloby lo apagas conshopt -u extglob.En su ejemplo, inicialmente haría:
La disposición completa ext terminó glob operadores de Bing son (extracto de
man bash):Entonces, por ejemplo, si quisiera enumerar todos los archivos en el directorio actual que no son
.co.harchivos, haría:Por supuesto, el gloging de shell normal funciona, por lo que el último ejemplo también podría escribirse como:
fuente
.co.hsea un directorio.D, pero no el contenido de los subdirectorios que pueden estar contenidos en el directorioD.No en bash (que yo sepa), pero:
Sé que esto no es exactamente lo que estabas buscando, pero resolverá tu ejemplo.
fuente
Si desea evitar el costo de usar el comando exec, creo que puede hacerlo mejor con xargs. Creo que lo siguiente es una alternativa más eficiente a
fuente
En bash, una alternativa a
shopt -s extglobes laGLOBIGNOREvariable . No es realmente mejor, pero me resulta más fácil recordarlo.Un ejemplo que puede ser lo que quería el póster original:
Cuando haya terminado,
unset GLOBIGNOREpara poderrm *techno*en el directorio de origen.fuente
También puedes usar un
forbucle bastante simple :fuente
-maxdepth 1para no recursivo?finden backticks se romperá de manera desagradable si encuentra nombres de archivos no triviales.Mi preferencia personal es usar grep y el comando while. Esto le permite a uno escribir scripts potentes pero legibles para asegurarse de que termine haciendo exactamente lo que quiere. Además, mediante el uso de un comando de eco puede realizar una ejecución en seco antes de llevar a cabo la operación real. Por ejemplo:
imprimirá los archivos que terminará copiando. Si la lista es correcta, el siguiente paso es simplemente reemplazar el comando echo con el comando copy de la siguiente manera:
fuente
bashpuede utilizarwhile IFS='' read -r filename, pero entonces nuevas líneas siguen siendo un problema. En general, es mejor no usarlspara enumerar archivos; herramientas comofindson mucho más adecuadas.for file in *; do case ${file} in (*Music*) ;; (*) cp "${file}" /target_directory ; echo ;; esac; doneUn truco que no he visto aquí sin embargo que no utiliza
extglob,findogrepes para tratar dos listas de archivos como conjuntos y "diff" utilizandocomm:commes preferiblediffporque no tiene cruft extra.Esto devuelve todos los elementos del conjunto 1
ls, que no están también en el conjunto 2ls *Music*,. Esto requiere que ambos conjuntos estén ordenados para funcionar correctamente. No hay problema para lalsexpansión global, pero si está utilizando algo comofind, asegúrese de invocarsort.Potencialmente útil.
fuente
comm -23 <(ls) exclude_these.listUna solución para esto se puede encontrar con find.
Find tiene bastantes opciones, puede ser bastante específico sobre lo que incluye y excluye.
Editar: Adam en los comentarios señaló que esto es recursivo. Las opciones de búsqueda mindepth y maxdepth pueden ser útiles para controlar esto.
fuente
find -maxdepth 1 -not -name '*Music*'/ target_directoryLos siguientes trabajos enumeran todos los
*.txtarchivos en el directorio actual, excepto aquellos que comienzan con un número.Esto funciona en
bash,dash,zshy todas las otras conchas compatibles con POSIX.En la línea uno, el patrón
/some/dir/*.txthará que elforbucle itere sobre todos los archivos/some/dircuyo nombre termine con.txt.En la línea dos se usa una declaración de caso para eliminar archivos no deseados. - La
${FILE##*/}expresión elimina cualquier componente de nombre de directorio principal del nombre de archivo (aquí/some/dir/) para que los patrones puedan coincidir solo con el nombre base del archivo. (Si solo está eliminando nombres de archivos basados en sufijos, puede acortar esto en su$FILElugar).En la línea tres, se omitirán todos los archivos que coincidan con el
casepatrón[0-9]*) (lacontinueinstrucción salta a la siguiente iteración delforbucle). - Si lo desea, puede hacer algo más interesante aquí, por ejemplo, como omitir todos los archivos que no comienzan con una letra (a – z)[!a-z]*, o puede usar múltiples patrones para omitir varios tipos de nombres de archivo, por ejemplo,[0-9]*|*.bakomitir archivos de ambos.bakarchivos y archivos que no comienzan con un número.fuente
*.txtlugar de solo*). Corregido ahora.esto lo haría excluyendo exactamente 'Música'
esto y aquello por excluir cosas como Música? * o *? Música
fuente
cppágina del manual en MacOS tiene una-aopción, pero hace algo completamente diferente. ¿Qué plataforma admite esto?