Usando expansão de parâmetro para gerar lista de argumentos para `mkdir -p`

10

Eu tenho algo parecido com isto:

% ls -1dF /tmp/foo/*
/tmp/foo/000f9e956feab3ee4625aebb65ae7bae9533cdbc/
/tmp/foo/002e34c2218f2c86fefd2876f0e5c2559c5fb3c4/
/tmp/foo/00b483576791bab751e6cb7ee0a7143af43a8069/
.
.
.
/tmp/foo/fedd0f7b545e7ae9600142656756456bc16874d3/
/tmp/foo/ff51ac87609012137cfcb02f36624f81cdc10788/
/tmp/foo/ff8b983a7411395344cad64182cb17e7cdefa55e/

Eu quero criar um diretório barem cada um dos subdiretórios em foo.

Se eu tentar fazer isso com

% mkdir -p /tmp/foo/*/bar

... eu recebo o erro

zsh: no matches found: /tmp/foo/*/bar

(Em retrospectiva, eu posso entender o motivo do erro.)

Eu sei que posso resolver o problema original com um loop for, mas estou curioso para saber se zshsuporta alguma forma de expansão de parâmetro que produziria o argumento desejado para uma única chamada de mkdir -p. IOW, uma expansão de parâmetro equivalente a "anexar /bara cada prefixo gerado pela expansão /tmp/foo/*", resultando em

% mkdir -p /tmp/foo/000f9e956feab3ee4625aebb65ae7bae9533cdbc/bar ... /tmp/foo/ff8b983a7411395344cad64182cb17e7cdefa55e/bar
kjo
fonte

Respostas:

13
setopt histsubstpattern extendedglob
mkdir -p /tmp/foo/*(#q/:s_%_/bar_)

Isso é um globbing estendido que possui um qsinalizador uiet glob que usa um qualificador glob para corresponder apenas a diretórios e um modificador para executar uma substitution (usando o %caractere padrão que está disponível apenas no modo padrão de substituição do histórico ) que anexa uma string a cada palavra.

man zshexpn
JdeBP
fonte
Uau, estou impressionado. Até encontrei tudo na página de manual que você especificou.
Curinga
1
Observe que o Pôster original foi especificado mkdir -p, o que teria um efeito ligeiramente diferente do seu comando de não gerar erros se alguns desses diretórios já tiverem barsubdiretórios. Ponto menor, mas vale a pena notar aqui. :)
Wildcard
1
Outra forma é a expansão gama uso via ${^spec}e acrescentar bara cada elemento do que quer que /tmp/foo/*(/)se expande para: set -- /tmp/foo/*(/)entãomkdir -p -- "${^@}/bar"
don_crissti
5

Claro - use um loop

for n in /tmp/foo/*; do mkdir "$n/bar";done

globs são usados ​​para expandir listas de itens existentes , não coisas que ainda não foram criadas.

Thomas Dickey
fonte
Desculpe, mas minha pergunta não foi claramente esclarecida. Eu vou esclarecer isso.
KJo
2
Isso não responde se é zshpossível expandir os globs e anexar texto com uma única sintaxe - mas acho que é provavelmente a única maneira de fazer o que você quer, @kjo.
Curinga
4

Se os diretórios estiverem em uma matriz, você poderá usar a ${^...}forma de expansão.

a=(/tmp/foo/*/)
mkdir -p ${^a}bar
chepner
fonte
0

Você pode usar finde xargsfazer isso:

find /tmp/foo -maxdepth 1 -mindepth 1 -type d | xargs -i echo mkdir -p {}/bar

que usa -maxdepth 1e -mindepth 1impede a criação de barsubdiretórios de destinos e, por /tmp/foosi só, respectivamente. type dfaz considerar apenas diretórios.

Você precisa remover echopara executar ações reais, caso contrário echo, apenas imprimirá linhas a serem executadas. Você também pode incluí-lo em substituição, como $()para executá-lo.

O manual diz que xargs -iestá obsoleto, mas não encontrei outra alternativa igualmente útil, por isso ainda deve funcionar por alguns anos ... Você pode substituir -ipor -I'{}'para estar atualizado com isso.

loa_in_
fonte
Esta resposta e a próxima parecem boas para mim. Alguém pode explicar por que eles deveriam receber votos negativos? Votos de baixa são bons, mas como podemos aprender se nenhuma razão for apresentada?
Joe
É uma alternativa de trabalho que não faz nada além do que o OP pediu. Me bate.
loa_in_
Eu acho que é algum tipo de preconceito que as respostas devem ter más respostas, então o preconceito afetou minha reputação.
loa_in_
Não gosto de votos inexplicáveis, mas não vi esse viés. Normalmente, respostas "ruins" (as que eu entendo) são realmente ruins.
21416 Joe
0

O @loa_in_ teve a maior parte, mas a findprodução da tubulação tende a ser um passo em falso.

find /tmp/foo -maxdepth 1 -mindepth 1 -type d -exec mkdir {}/bar \;
Sammitch
fonte
Eu apenas uso xargscom ferramentas diferentes que não têm -execalternativa, então uso minha abordagem, pois ela trabalha com todas igualmente.
loa_in_