GNU/Linux >> Znalost Linux >  >> Linux

Selhalo přesměrování na název souboru Globbed?

Používám Bash 4.3.48(1) v Ubuntu 16.04 (xenial) se zásobníkem LEMP.

Snažím se vytvořit php.ini přepíše soubor způsobem bez ohledu na verzi pomocí printf .

1) Operace zjištění verze se nezdaří:

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

Zobrazí se následující chyba:

bash:/etc/php/*/zz_overrides.ini:Žádný takový soubor nebo adresář

2) Gnostická operace verze je úspěšná:

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

Jak můžete vidět, oba jsou v podstatě totožné kromě * vs 7.0 .

  • Nenašel jsem ponětí o tomto (regulárním výrazu?) problému v man printf .
  • Hledal jsem na Googlu a nenašel jsem nic o „povolení regulárního výrazu v printf“.

Proč se nezdaří operace rozpoznání verze a existuje nějaké vynechání?

Edit:Pokud je to možné, je pro mě nejdůležitější použít jednořádkovou operaci.

Přijatá odpověď:

Zdá se, že chování shody vzoru při přesměrování se mezi shelly liší. Z těch v mém systému, pomlčka a ksh93 nerozšiřují vzor, ​​takže získáte název souboru s doslovným * . Bash jej rozšíří, ale pouze v případě, že vzor odpovídá jednomu souboru. Stěžuje si, pokud existuje více odpovídajících názvů souborů. Zsh funguje, jako byste dali více přesměrování, přesměruje výstup na všechny odpovídající soubory.

(1) kromě případů, kdy je neinteraktivní a v režimu POSIX

Pokud chcete, aby výstup šel do všech odpovídajících souborů, můžete použít tee :

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

Pokud chcete, aby to šlo pouze do jednoho souboru, problém je rozhodnout se, který z nich použít. Pokud chcete zkontrolovat, že vzoru odpovídá pouze jeden soubor, rozbalte celý seznam a spočítejte je.

V 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

Ve standardním prostředí set poziční parametry a použijte $# pro počítání.

Samozřejmě, pokud vzor neodpovídá žádnému souboru, je ponechán tak, jak je, a protože globus je uprostřed, výsledek ukazuje na neexistující adresář. Je to stejné, jako když se pokoušíte vytvořit /path/to/file , před /path/to existuje, jen zde máme /path/* místo toho doslova s ​​hvězdičkou.

Abyste se s tím vypořádali, museli byste rozbalit názvy adresářů bez názvu souboru a poté přidat název souboru ke všem adresářům. To je trochu ošklivé…

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

a pak můžeme použít toto pole:

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

Nebo bychom mohli použít snadný způsob a opakovat vzor názvu souboru. V obecnějším případě je to trochu neuspokojivé, protože vyžaduje spuštění hlavního příkazu jednou pro každý výstupní soubor nebo použití dočasného souboru k uložení výstupu.

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

Linux
  1. Přesměrovat na stejný soubor jako zdrojový soubor zpracovaný příkazem?

  2. Vytvoření prázdného souboru s názvem proměnné ve skriptu?

  3. Pochopení souboru /etc/hosts v Linuxu

  1. Jak poznám název souboru skriptu ve skriptu Bash?

  2. Odeberte symbolický odkaz na adresář

  3. mkdir -p selže, když adresář existuje

  1. Přesměrování vstupu/výstupu v Linuxu/Unixu

  2. Vytvoření souboru CSR webového certifikátu.

  3. cp-L vs. cp-H