GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Die Umleitung zu einem globbed-Dateinamen schlägt fehl?

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 

Linux
  1. Erstellen einer Webzertifikat-CSR-Datei.

  2. In dieselbe Datei wie die vom Befehl verarbeitete Quelldatei umleiten?

  3. Erstellen einer leeren Datei mit einem Variablennamen in einem Skript?

  4. /etc/hosts-Datei unter Linux verstehen

  5. Woher weiß ich den Namen der Skriptdatei in einem Bash-Skript?

Bash-Umleitung mit Beispielen erklärt

Grep findet keinen Text in dieser Datei?

Shell-Scripting Teil 4 – Eingabe, Ausgabe und Umleitung

Pipes und Redirection in Linux - erklärt!

Wie lösche ich eine Datei mit einem seltsamen Namen?

Linux-mv-Datei mit langem Namen