GNU/Linux >> Linux Esercitazione >  >> Linux

Il reindirizzamento a un nome di file Globbed non riesce?

Uso Bash 4.3.48(1) in Ubuntu 16.04 (xenial) con uno stack LEMP.

Provo a creare un php.ini overrides in modo indipendente dalla versione con printf .

1) L'operazione indipendente dalla versione non riesce:

printf "[PHP]n post_max_size = 200Mn upload_max_filesize = 200Mn cgi.fix_pathinfo = 0" > /etc/php/*/fpm/zz_overrides.ini

Viene visualizzato il seguente errore:

bash:/etc/php/*/zz_overrides.ini:nessun file o directory di questo tipo

2) L'operazione gnostica della versione ha esito positivo:

printf "[PHP]n post_max_size = 200Mn upload_max_filesize = 200Mn cgi.fix_pathinfo = 0" > /etc/php/7.0/fpm/zz_overrides.ini

Come puoi vedere, entrambi sono sostanzialmente identici oltre a * rispetto a 7.0 .

  • Non ho trovato la minima idea di questo problema (regex?) in man printf .
  • Ho cercato su Google e non ho trovato nulla su "consentire l'espressione regolare in printf".

Perché l'operazione indipendente dalla versione non riesce ed è presente un bypass?

Modifica:se possibile, è molto importante per me utilizzare un'operazione su una riga.

Risposta accettata:

Il comportamento di una corrispondenza di pattern in un reindirizzamento sembra differire tra le shell. Di quelli sul mio sistema, dash e ksh93 non espandono il modello, quindi ottieni un nome file con un * letterale . Bash lo espande, ma solo se il modello corrisponde a un file. Si lamenta se ci sono più nomi di file che corrispondono. Zsh funziona come se avessi fornito più reindirizzamenti, reindirizza l'output a tutti file corrispondenti.

(1) tranne quando non è interattivo e in modalità POSIX

Se vuoi che l'output vada a tutti i file corrispondenti, puoi usare tee :

echo ... | tee /path/*/file > /dev/null

Se vuoi che vada su un solo file, il problema è decidere quale usare. Se vuoi verificare che ci sia un solo file che corrisponde al modello, espandi l'intero elenco e contali.

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

Nella shell standard, set i parametri posizionali e usa $# per il conteggio.

Ovviamente, se il modello non corrisponde a nessun file, viene lasciato così com'è e poiché il glob si trova nel mezzo, il risultato punta a una directory inesistente. È come provare a creare /path/to/file , prima di /path/to esiste, è solo qui che abbiamo /path/* invece, letteralmente, con l'asterisco.

Per far fronte a ciò, dovresti espandere i nomi delle directory senza il nome del file, quindi aggiungere il nome del file a tutte le directory. Questo è un po' brutto...

dirs=(/path/*)
files=( "${dirs[@]/%//file}" )

e quindi possiamo usare quell'array:

echo ... | tee "${files[@]}" > /dev/null

Oppure potremmo prendere la via più semplice e scorrere il modello del nome del file. È un po' insoddisfacente nel caso più generale, poiché richiede l'esecuzione del comando principale una volta per ogni file di output o l'utilizzo di un file temporaneo per contenere l'output.

for dir in /path/* ; do
    echo ... > "$dir/file"
done 

Linux
  1. Reindirizzamento input/output in Linux/Unix

  2. Io reindirizzamento e il comando principale?

  3. Reindirizzamento allo stesso file del file di origine elaborato dal comando?

  4. Creare un file vuoto con un nome di variabile in uno script?

  5. Grep non riesce a trovare il testo in questo file?

Reindirizzamento Bash spiegato con esempi

Creazione di un file CSR del certificato Web.

Come modificare un nome di file contenente caratteri?

Shell Scripting Part4 – Input, Output e Reindirizzamento

cp -L contro cp -H

File Linux mv con nome lungo