Snažím se napsat if příkaz k testování, zda existují nějaké soubory odpovídající určitému vzoru. Pokud je v adresáři textový soubor, měl by spustit daný skript.
Můj kód aktuálně:
if [ -f /*.txt ]; then ./script fi
Uveďte prosím nějaké nápady; Skript chci spustit pouze v případě, že existuje .txt v adresáři.
Přijatá odpověď:
[ -f /*.txt ]
vrátí true, pouze pokud existuje jeden (a pouze jeden) neskrytý soubor v / jehož jméno končí na .txt a pokud je tento soubor běžným souborem nebo symbolickým odkazem na běžný soubor.
Je to proto, že zástupné znaky jsou před předáním příkazu rozbaleny shellem (zde [ ).
Pokud tedy existuje /a.txt a /b.txt , [ bude předáno 5 argumentů:[ , -f , /a.txt , /b.txt a ] . [ by si pak stěžoval, že -f je uvedeno příliš mnoho argumentů.
Pokud chcete zkontrolovat, že *.txt vzor se rozšíří na alespoň jeden neskrytý soubor (běžný nebo ne) v bash shell:
shopt -s nullglob
set -- *.txt
if [ "$#" -gt 0 ]; then
./script "[email protected]" # call script with that list of files.
fi
# Or with bash arrays so you can keep the arguments:
files=( *.txt )
# apply C-style boolean on member count
(( ${#files[@]} )) && ./script "${files[@]}"
shopt -s nullglob je bash konkrétní (shopt je nullglob ve skutečnosti pochází z zsh ), ale shelly jako ksh93 , zsh , yash , tcsh mít ekvivalentní prohlášení.
Pomocí zsh , test na existují soubory odpovídající vzoru lze zapsat pomocí anonymní funkce a N (pro nullglob ) a Y1 (pro zastavení po prvním nalezení) kvalifikátor glob:
if ()(($#)) *.txt(NY1); then
do-something
fi
Všimněte si, že tito najdou tyto soubory čtením obsahu adresáře, vůbec se nepokouší o přístup k těmto souborům, což je efektivnější než řešení, která volají příkazy jako ls nebo stat na tomto seznamu souborů vypočítaných shellem.
Standardní sh ekvivalent by byl:
set -- [*].txt *.txt
case "$1$2" in
('[*].txt*.txt') ;;
(*) shift; script "[email protected]"
esac
Problém je v tom, že u shellů Bourne nebo POSIX, pokud vzor neodpovídá, roztáhne se sám na sebe. Pokud tedy *.txt se rozšíří na *.txt , nevíte, zda je to tím, že neexistuje žádný .txt soubor v adresáři nebo protože existuje jeden soubor s názvem *.txt . Pomocí [*].txt *.txt umožňuje rozlišovat mezi těmito dvěma.
Nyní, pokud chcete zkontrolovat, že *.txt odpovídá alespoň jednomu běžnému soubor nebo symbolický odkaz na běžný soubor (jako váš [ -f *.txt ] navrhuje, že chcete udělat), nebo že všechny soubory, které odpovídají *.txt jsou pravidelné soubory (po rozlišení symbolických odkazů), to je další věc.
Pomocí zsh :
if ()(($#)) *.txt(NY1-.); then
echo "there is at least one regular .txt file"
fi
if ()(($#)) *.txt(NY1^-.); then
echo "there is at least one non-regular .txt files"
fi
(odstraňte - pokud chcete provést test před rozlišením symbolických odkazů, považujte symbolické odkazy za nestandardní soubory, ať už odkazují na běžné soubory nebo ne).