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
extglob
opción de shell le ofrece una coincidencia de patrones más potente en la línea de comandos.Lo enciendes
shopt -s extglob
y 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
.c
o.h
archivos, haría:Por supuesto, el gloging de shell normal funciona, por lo que el último ejemplo también podría escribirse como:
fuente
.c
o.h
sea 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 extglob
es laGLOBIGNORE
variable . 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 GLOBIGNORE
para poderrm *techno*
en el directorio de origen.fuente
También puedes usar un
for
bucle bastante simple :fuente
-maxdepth 1
para no recursivo?find
en 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
bash
puede utilizarwhile IFS='' read -r filename
, pero entonces nuevas líneas siguen siendo un problema. En general, es mejor no usarls
para enumerar archivos; herramientas comofind
son mucho más adecuadas.for file in *; do case ${file} in (*Music*) ;; (*) cp "${file}" /target_directory ; echo ;; esac; done
Un truco que no he visto aquí sin embargo que no utiliza
extglob
,find
ogrep
es para tratar dos listas de archivos como conjuntos y "diff" utilizandocomm
:comm
es preferiblediff
porque 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 lals
expansión global, pero si está utilizando algo comofind
, asegúrese de invocarsort
.Potencialmente útil.
fuente
comm -23 <(ls) exclude_these.list
Una 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
*.txt
archivos en el directorio actual, excepto aquellos que comienzan con un número.Esto funciona en
bash
,dash
,zsh
y todas las otras conchas compatibles con POSIX.En la línea uno, el patrón
/some/dir/*.txt
hará que elfor
bucle itere sobre todos los archivos/some/dir
cuyo 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$FILE
lugar).En la línea tres, se omitirán todos los archivos que coincidan con el
case
patrón[0-9]*
) (lacontinue
instrucción salta a la siguiente iteración delfor
bucle). - 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]*|*.bak
omitir archivos de ambos.bak
archivos y archivos que no comienzan con un número.fuente
*.txt
lugar 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
cp
página del manual en MacOS tiene una-a
opción, pero hace algo completamente diferente. ¿Qué plataforma admite esto?