W jaki sposób możesz sprawdzić, czy pliki o określonym rozszerzeniu znajdują się w katalogu za pomocą bash?
Coś jak
if [ -e *.flac ]; then
echo true;
fi
Odpowiedzi:
#!/bin/bash
count=`ls -1 *.flac 2>/dev/null | wc -l`
if [ $count != 0 ]
then
echo true
fi
ls -l
, moja odpowiedź używals -1
ls -1
wydrukuje jedną linię na plik
\n
(i tak, jest to poprawne w nazwach plików).
#/bin/bash
myarray=(`find ./ -maxdepth 1 -name "*.py"`)
if [ ${#myarray[@]} -gt 0 ]; then
echo true
else
echo false
fi
${#myarray[@]}
to 1
ls -1 *.py
zamiast find
Używa ls (1), jeśli nie istnieją żadne pliki flac, ls zgłasza błąd i skrypt kończy pracę; w przeciwnym razie skrypt jest kontynuowany, a pliki mogą być przetwarzane
#! /bin/sh
ls *.flac >/dev/null || exit
## Do something with flac files here
if ls *.flac >/dev/null 2>&1; then ... fi;
shopt -s nullglob
if [[ -n $(echo *.flac) ]] # or [ -n "$(echo *.flac)" ]
then
echo true
fi
Musisz uważać, którą flagę wrzucisz do swojego if
oświadczenia i jaki ma to związek z oczekiwanym wynikiem.
Jeśli chcesz sprawdzić tylko zwykłe pliki, a nie inne typy wpisów systemu plików, będziesz chciał zmienić szkielet kodu na:
if [ -f file ]; then
echo true;
fi
Użycie -f
ograniczenia ogranicza się if
do zwykłych plików, podczas gdy -e
jest bardziej ekspansywne i będzie pasować do wszystkich typów wpisów systemu plików. Istnieją oczywiście inne opcje, takie jak -d
katalogi itp. Zobacz http://tldp.org/LDP/abs/html/fto.html aby uzyskać dobrą listę.
Jak wskazał @msw, test
(tj. [
) Dusi się, jeśli spróbujesz podać więcej niż jeden argument. Może się to zdarzyć w twoim przypadku, jeśli glob for *.flac
zwrócił więcej niż jeden plik. W takim przypadku spróbuj zawinąć if
test w pętlę, taką jak:
for file in ./*.pdf
do
if [ -f "${file}" ]; then
echo 'true';
break
fi
done
W ten sposób break
na pierwszym wystąpieniu żądanego rozszerzenia pliku możesz kontynuować pracę nad resztą skryptu.
test
(aka [
) narzeka, jeśli wzorzec rozwija się do więcej niż jednego pliku: „oczekiwano operatora binarnego” lub „za dużo argumentów”
"$file"
, ponieważ nazwa pliku może zawierać złe znaki, takie jak spacje lub gwiazdki.
Najlepsze rozwiązanie (if [ -e *.flac ];)
u mnie nie działało, dając:[: too many arguments
if ls *.flac >/dev/null 2>&1;
wtedy to zadziała.
Możesz użyć -f, aby sprawdzić, czy istnieją pliki określonego typu:
#!/bin/bash
if [ -f *.flac ] ; then
echo true
fi
[
(w przeciwieństwie do bardziej powszechnego [[
) nie zapobiega globbingowi.
shopt -s nullglob
set -- $(echo *.ext)
if [ "${#}" -gt 0 ];then
echo "got file"
fi
-ge
zamiast tego -gt
, ponieważ w przeciwnym razie kod nie wykryje pojedynczego pliku. Po drugie, jeśli nie ma plików pasujących do wzorca, każda zgodna powłoka pozostawi ciąg *.ext
nietknięty, więc nadal otrzymasz jeden „wynik”.
tylko bash:
any_with_ext () (
ext="$1"
any=false
shopt -s nullglob
for f in *."$ext"; do
any=true
break
done
echo $any
)
if $( any_with_ext flac ); then
echo "have some flac"
else
echo "dir is flac-free"
fi
Używam nawiasów zamiast nawiasów klamrowych, aby upewnić się, że używana jest podpowłoka (nie chcę przebijać bieżących nullglob
ustawień).
Oto rozwiązanie wykorzystujące bez zewnętrznych poleceń (tj. Nie ls
), ale zamiast tego funkcję powłoki. Przetestowane w bash:
shopt -s nullglob
function have_any() {
[ $# -gt 0 ]
}
if have_any ./*.flac; then
echo true
fi
Funkcja have_any
używa $#
do liczenia argumentów, a [ $# -gt 0 ]
następnie sprawdza, czy istnieje co najmniej jeden argument. Użycie ./*.flac
zamiast tylko *.flac
w wywołaniu funkcji have_any
ma na celu uniknięcie problemów powodowanych przez pliki o nazwach takich jak --help
.
Aby zakończyć, z zsh:
if [[ -n *.flac(#qN) ]]; then
echo true
fi
Jest to wymienione na końcu sekcji Wyrażenia warunkowe w podręczniku zsh. Ponieważ [[
wyłącza tworzenie nazw plików, musimy wymusić generowanie nazwy pliku, używając (#q)
na końcu globalnego ciągu znaków, a następnie N
flagi ( NULL_GLOB
opcji), aby wymusić, że wygenerowany ciąg będzie pusty w przypadku braku dopasowania.
Oto dość proste rozwiązanie:
if [ "$(ls -A | grep -i \\.flac\$)" ]; then echo true; fi
Jak widać, jest to tylko jedna linia kodu, ale działa wystarczająco dobrze. Powinien działać zarówno z bashem, jak i powłoką zgodną z POSIX, taką jak myślnik. Rozróżnia również wielkość liter i nie dba o to, jakie typy plików (zwykłe, dowiązanie symboliczne, katalog itp.) Są obecne, co może być przydatne, jeśli masz jakieś dowiązania symboliczne lub coś w tym rodzaju.
Próbowałem tego:
if [ -f *.html ]; then
echo "html files exist"
else
echo "html files dont exist"
fi
Użyłem tego fragmentu kodu bez problemu dla innych plików, ale dla plików html otrzymałem błąd :
[: too many arguments
Następnie wypróbowałem rozwiązanie zliczania @ JeremyWeir, które zadziałało dla mnie.
Pamiętaj, że będziesz musiał zresetować licznik, jeśli robisz to w pętli:
count=$((0))
To powinno działać w każdej skorupie podobnej do przenoszonej:
if [ "$(find . -maxdepth 1 -type f | grep -i '.*\.flac$')" ]; then
echo true
fi
Działa to również z GNU find
, ale IDK, jeśli jest to zgodne z innymi implementacjami find
:
if [ "$(find . -maxdepth 1 -type f -iname \*.flac)" ]; then
echo true
fi