Wykorzystanie rozszerzenia parametrów do wygenerowania listy argumentów dla `mkdir -p`

10

Mam coś takiego:

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

Chcę utworzyć katalog barw każdym z podkatalogów foo.

Jeśli spróbuję to zrobić

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

... dostaję błąd

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

(Z perspektywy czasu rozumiem przyczynę błędu.)

Wiem, że mogę rozwiązać pierwotny problem za pomocą pętli for, ale jestem ciekawy, czy zshobsługuje jakąś formę rozszerzenia parametrów, która wygenerowałaby pożądany argument dla pojedynczego wywołania mkdir -p. IOW, rozszerzenie parametru równoważne „dołączaniu /bardo każdego prefiksu generowanego przez rozwijanie /tmp/foo/*”, w wyniku czego

% mkdir -p /tmp/foo/000f9e956feab3ee4625aebb65ae7bae9533cdbc/bar ... /tmp/foo/ff8b983a7411395344cad64182cb17e7cdefa55e/bar
kjo
źródło

Odpowiedzi:

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

Jest to rozszerzone globowanie, które ma qflagę globu uiet, która używa kwalifikatora globu, aby dopasować tylko katalogi, oraz modyfikatora do wykonania substytucji (przy użyciu %znaku wzorca dostępnego tylko w trybie wzorca zastępowania historii ), który dołącza ciąg do każdego słowa.

man zshexpn
JdeBP
źródło
Wow jestem pod wrażeniem. Znalazłem to wszystko na stronie podręcznika, którą określiłeś.
Wildcard
1
Zauważ, że podałeś Oryginalny Plakat mkdir -p, który miałby nieco inny efekt niż twoje polecenie nie rzucania błędów, jeśli niektóre z tych katalogów mają już barpodkatalogi. Drobny punkt, ale warto tutaj zauważyć. :)
Wildcard,
1
Innym sposobem jest użycie rozszerzenia tablicy za pomocą ${^spec}i dołączenie bardo każdego elementu dowolnego elementu /tmp/foo/*(/)set -- /tmp/foo/*(/)mkdir -p -- "${^@}/bar"
rozwijanego
5

Jasne - użyj pętli

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

globusy służą do rozwijania list istniejących elementów, a nie rzeczy, które nie zostały jeszcze utworzone.

Thomas Dickey
źródło
Przepraszam, obawiam się, że moje pytanie nie zostało jasno określone. Wyjaśnię to.
kjo
2
To nie odpowiada, czy zshmożna rozwinąć globusy i dołączyć tekst za pomocą jednej składni - ale myślę, że to prawdopodobnie jedyny sposób na robienie tego, co chcesz, @ kjo.
Wildcard
4

Jeśli katalogi są w tablicy, możesz użyć ${^...}formy rozszerzenia.

a=(/tmp/foo/*/)
mkdir -p ${^a}bar
chepner
źródło
0

Możesz użyć findi xargszrobić to:

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

który wykorzystuje -maxdepth 1i -mindepth 1zapobiega tworzeniu barw podkatalogach celów i /tmp/fooodpowiednio w sobie. type dsprawia, że ​​bierze pod uwagę tylko katalogi.

Musisz usunąć, echoaby wykonać rzeczywiste działania, w przeciwnym razie echowydrukuje tylko wiersze do wykonania. Możesz również dołączyć go do zamiany, tak jak $()go wykonać.

Instrukcja mówi, xargs -ijest przestarzałe, ale znalazłem żadnej innej alternatywy równie poręczne, więc powinien nadal pracować przez kilka lat ... Można wymieniać -isię -I'{}'aby być na bieżąco z tym.

loa_in_
źródło
Ta odpowiedź i następna wyglądają dla mnie dobrze. Czy ktoś może wyjaśnić, dlaczego należy głosować w dół? Głosy w dół są w porządku, ale jak możemy się dowiedzieć, jeśli nie podano żadnych powodów?
Joe
Jest to działająca alternatywa, która nie robi nic poza pytaniem OP. Bije mnie
loa_in_
Wydaje mi się, że z jakiegoś rodzaju stronniczości odpowiedzi muszą zawierać złe odpowiedzi, więc uprzedzenia odbiły się na mojej reputacji.
loa_in_
Nie lubię niewyjaśnionych głosów, ale nie widziałem takiego uprzedzenia. Zwykle „złe” odpowiedzi (te, które rozumiem) są w rzeczywistości złe.
Joe
0

@loa_in_ miał większość tego, ale finddane wyjściowe w potokach wydają się być faux pas.

find /tmp/foo -maxdepth 1 -mindepth 1 -type d -exec mkdir {}/bar \;
Sammitch
źródło
Po prostu używam xargsz różnymi narzędziami, które nie mają -execalternatywy, więc używam mojego podejścia, ponieważ działa z nimi wszystkimi jednakowo.
loa_in_