Ich verwende Bash 4.3.48(1) in Ubuntu 16.04 (xenial) mit einem LEMP-Stack.
Ich versuche, eine php.ini
zu erstellen overridings-Datei in einer versionagnostischen Weise mit printf
.
1) Der versionunabhängige Vorgang schlägt fehl:
printf "[PHP]n post_max_size = 200Mn upload_max_filesize = 200Mn cgi.fix_pathinfo = 0" > /etc/php/*/fpm/zz_overrides.ini
Der folgende Fehler wird ausgegeben:
bash:/etc/php/*/zz_overrides.ini:Keine solche Datei oder Verzeichnis
2) Die Versions-gnostische Operation ist erfolgreich:
printf "[PHP]n post_max_size = 200Mn upload_max_filesize = 200Mn cgi.fix_pathinfo = 0" > /etc/php/7.0/fpm/zz_overrides.ini
Wie Sie sehen, sind beide bis auf *
grundsätzlich identisch im Vergleich zu 7.0
.
- Ich habe in
man printf
keinen Hinweis auf dieses (regex?) Problem gefunden . - Ich habe in Google gesucht und nichts über „Regex in printf zulassen“ gefunden.
Warum schlägt der versionunabhängige Vorgang fehl und gibt es eine Umgehung?
Edit:Wenn möglich, ist es mir am wichtigsten, eine einzeilige Operation zu verwenden.
Akzeptierte Antwort:
Das Verhalten einer Musterübereinstimmung in einer Umleitung scheint sich zwischen Shells zu unterscheiden. Von denen auf meinem System erweitern dash und ksh93 das Muster nicht, sodass Sie einen Dateinamen mit einem wörtlichen *
erhalten . Bash erweitert es, aber nur, wenn das Muster mit einer Datei übereinstimmt. Es beschwert sich, wenn es mehr übereinstimmende Dateinamen gibt. Zsh funktioniert so, als ob Sie mehrere Umleitungen gegeben hätten, es leitet die Ausgabe auf alle um passenden Dateien.
(1) außer wenn es nicht interaktiv und im POSIX-Modus ist
Wenn Sie möchten, dass die Ausgabe an alle übereinstimmenden Dateien geht, können Sie tee
verwenden :
echo ... | tee /path/*/file > /dev/null
Wenn Sie möchten, dass es nur in eine Datei geht, müssen Sie entscheiden, welche Sie verwenden möchten. Wenn Sie überprüfen möchten, ob es nur eine Datei gibt, die dem Muster entspricht, erweitern Sie die gesamte Liste und zählen Sie sie.
In bash/ksh:
names=(/path/*/file)
if [ "${#names[@]}" -gt 1 ] ; then
echo "there's more than one"
else
echo "there's only one: ${names[0]}"
fi
In der Standard-Shell set
die Positionsparameter und verwenden Sie $#
für die Zählung.
Wenn das Muster zu keiner Datei passt, wird es natürlich unverändert gelassen, und da sich der Glob in der Mitte befindet, zeigt das Ergebnis auf ein nicht vorhandenes Verzeichnis. Es ist dasselbe wie zu versuchen, /path/to/file
zu erstellen , vor /path/to
existiert, nur hier haben wir /path/*
stattdessen wörtlich mit dem Sternchen.
Um damit umzugehen, müssten Sie den/die Verzeichnisnamen ohne den Dateinamen erweitern und dann den Dateinamen an alle Verzeichnisse anhängen. Das ist ein bisschen hässlich…
dirs=(/path/*)
files=( "${dirs[@]/%//file}" )
und dann können wir dieses Array verwenden:
echo ... | tee "${files[@]}" > /dev/null
Oder wir könnten den einfachen Ausweg nehmen und das Dateinamenmuster wiederholen. Im allgemeineren Fall ist dies etwas unbefriedigend, da der Hauptbefehl einmal für jede Ausgabedatei ausgeführt werden muss oder eine temporäre Datei zum Speichern der Ausgabe verwendet werden muss.
for dir in /path/* ; do
echo ... > "$dir/file"
done