É um padrão glob estendido zsh. O objetivo é combinar todos os arquivos com um padrão em uma hierarquia de diretórios, com exceção de sub-hierarquias específicas. O padrão no título funciona, mas eu queria algo que não exigisse repetição long/path/
.
Eu tentei o seguinte:
long/path/(^(bad-1|bad-2)/|)**/^*.(complex|pattern)(.)
long/path/(**~(bad-1|bad-2)/*)/^*.(complex|pattern)(.)
com KSH_GLOB
adicionado:
long/path/?(^(bad-1|bad-2)/)**/^*.(complex|pattern)(.)
Todos eles resultam em um erro de padrão ruim. Parece que o problema é ter um /
entre parênteses. A documentação diz:
Como mencionado acima, um `/' usado como separador de diretório pode não aparecer entre parênteses
Isso me confundiu porque (dir/)#
é um bom padrão. É até mencionado nos documentos:
Um componente de nome de caminho no formato `(foo/)#' corresponde a um caminho que consiste em zero ou mais diretórios correspondentes ao padrão foo.
Acho que é a exceção.
Para ser claro, estou procurando equivalentes. Isso exclui:
long/path/^(bad-1|bad-2)/**/^*.(complex|pattern)(.)
uma vez que exclui coisas como long/path/good.pattern
, e
long/path/(^(bad-1|bad-2)/)#/^*.(complex|pattern)(.)
long/path/**/^*.(complex|pattern)~*/(bad-1|bad-2)/*(.)
uma vez que excluem coisas como o que está sob long/path/good/bad-1
.
EDIT: Só para mencionar, uma solução não precisa necessariamente usar apenas globbing. Se isso puder ser feito adicionando o uso de brace ou expansão de histórico ou algum outro recurso zsh, isso é ótimo.
EDIT 2: Seguindo minhas próprias ideias, tentei a expansão do histórico:
long/path/**/^*.(complex|pattern)~!{#$:s/\**//}/(bad-1|bad-2)/*(.)
No entanto, isso falhou porque 1) a última palavra da linha atual é a anterior àquela em que a expansão está e 2) porque a substituição do histórico parece ser feita após a expansão glob (devo estar entendendo mal algo aqui porque isso parece para ir contra os documentos; talvez todas as expansões sejam feitas palavra por palavra).
Eu também tentei expansão de chaves:
( IFS=\~; printf "%s\n" long/path/{**/^*.(complex|pattern),(bad-1|bad-2)/*(.)} )
Não funcionou. Os 2 padrões glob ainda foram tomados como palavras separadas em vez de serem unidos em um único padrão. Eu acho que IFS
não é levado em consideração aqui. Faz sentido.
Eu também tentei substituição em qualificadores glob:
+/**/^*.(complex|pattern)~+/(bad-1|bad-2)/*(.:s,+,long/path,)
Mas, é claro, isso não funcionaria porque a substituição seria feita após a correspondência, não antes.
Entendi! Barras duplas para marcar o prefixo:
Às vezes você não percebe que algo é um recurso até encontrar um uso para isso. Eu não posso acreditar que o fato de que as barras contíguas são equivalentes a uma pode realmente ser tão útil. :)
Os documentos para
(...)
lista/
como uma exceção:A repetição pode ser evitada usando uma expressão para filtrar os resultados: