Verwenden der Parametererweiterung zum Generieren einer Argumentliste für `mkdir -p`


10

Ich habe so etwas:

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

Ich möchte ein Verzeichnis barunter jedem der Unterverzeichnisse unter erstellen foo.

Wenn ich das versuche mit

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

... Ich bekomme den Fehler

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

(Im Nachhinein kann ich den Grund für den Fehler verstehen.)

Ich weiß, dass ich das ursprüngliche Problem mit einer for-Schleife lösen kann, aber ich bin gespannt, ob zsheine Form der Parametererweiterung unterstützt wird, die das gewünschte Argument für einen einzelnen Aufruf von erzeugt mkdir -p. IOW, eine Parametererweiterung, die " /baran jedes durch Erweitern erzeugte Präfix anhängen /tmp/foo/*" entspricht

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

Antworten:


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

Dies ist ein erweitertes Globbing mit einem quiet glob- Flag , das ein glob-Qualifikationsmerkmal verwendet , um nur Verzeichnisse abzugleichen, und einem Modifikator , um eine sUbstitution durchzuführen (unter Verwendung des %Musterzeichens, das nur im Verlaufssubstitutionsmustermodus verfügbar ist ), das jedem Wort eine Zeichenfolge anfügt.

man zshexpn

Wow, ich bin beeindruckt. Ich habe sogar alles in der von Ihnen angegebenen Manpage gefunden.
Wildcard

1
Beachten Sie, dass das Originalposter angegeben wurde mkdir -p, was sich geringfügig von Ihrem Befehl unterscheidet, keine Fehler auszulösen, wenn einige dieser Verzeichnisse bereits barUnterverzeichnisse haben. Kleiner Punkt, aber hier erwähnenswert. :)
Wildcard

1
Eine andere Möglichkeit besteht darin, die Array-Erweiterung über zu verwenden ${^spec}und baran jedes Element anzuhängen, auf das /tmp/foo/*(/)erweitert wird: set -- /tmp/foo/*(/)thenmkdir -p -- "${^@}/bar"
don_crissti

5

Sicher - benutze eine Schleife

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

Globs werden verwendet, um Listen vorhandener Elemente zu erweitern , nicht Dinge, die noch nicht erstellt wurden.


Entschuldigung, ich fürchte, meine Frage wurde nicht klar gestellt. Ich werde es klarstellen.
Kjo

2
Dies antwortet nicht, wenn zshGlobs erweitert und Text mit einer einzigen Syntax angehängt werden kann - aber ich denke, es ist wahrscheinlich die einzige Möglichkeit, das zu tun, was Sie wollen, @kjo.
Wildcard

4

Wenn sich die Verzeichnisse in einem Array befinden, können Sie die ${^...}Form der Erweiterung verwenden.

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

0

Sie können es verwenden findund xargstun:

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

die Verwendung -maxdepth 1und -mindepth 1Verhinderung der Erstellung von barUnterverzeichnissen von Zielen bzw. an /tmp/foosich. type dLässt es nur Verzeichnisse berücksichtigen.

Sie müssen entfernen echo, um tatsächliche Aktionen echoauszuführen. Andernfalls werden nur die auszuführenden Zeilen ausgedruckt. Sie können es auch in eine Substitution einschließen $(), um es auszuführen.

Handbuch sagt xargs -iist veraltet, aber ich fand keine andere ebenso praktische Alternative, so sollte es immer noch Arbeit seit einigen Jahren ... Sie können ersetzen -imit -I'{}'zu up-to-date mit dem.


Diese und die nächste Antwort sehen für mich gut aus. Kann jemand erklären, warum sie abgelehnt werden sollten? Abwärtsstimmen sind in Ordnung, aber wie können wir lernen, wenn keine Gründe angegeben werden?
Joe

Es ist eine funktionierende Alternative, die nur das tut, was OP verlangt hat. Schlägt mich.
Loa_in_

Ich denke, es ist eine Art Voreingenommenheit, dass Antworten schlechte Antworten haben müssen, also haben Vorurteile meinen Ruf belastet.
Loa_in_

Ich mag keine ungeklärten Abstimmungen, aber ich habe keine solche Voreingenommenheit gesehen. Normalerweise sind "schlechte" Antworten (die ich verstehe) tatsächlich schlecht.
Joe

0

@loa_in_ hatte das meiste davon, aber die Piping- findAusgabe ist in der Regel ein Fauxpas.

find /tmp/foo -maxdepth 1 -mindepth 1 -type d -exec mkdir {}/bar \;

Ich benutze nur xargsverschiedene Tools, die keine -execAlternative haben, also verwende ich meinen Ansatz, da er mit allen gleichermaßen funktioniert.
Loa_in_
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.