Użyłem następującego skryptu, aby sprawdzić, czy plik istnieje:
#!/bin/bash
FILE=$1
if [ -f $FILE ]; then
echo "File $FILE exists."
else
echo "File $FILE does not exist."
fi
Jakiej poprawnej składni użyć, jeśli chcę tylko sprawdzić, czy plik nie istnieje?
#!/bin/bash
FILE=$1
if [ $FILE does not exist ]; then
echo "File $FILE does not exist."
fi
if [ -f $FILE ]; then; else; echo "File $FILE does not exist."; fi;
Prawdopodobnie dobrze, że znalazłem to pytanie i nauczyłem się robić to we właściwy sposób. :)-e
. -f nie odbiera katalogów, dowiązań symbolicznych itp.FILE=$1
FILE="$1"
if [ -f $FILE ];
if [ -f "$FILE" ];
Odpowiedzi:
Polecenie testowe (
[
tutaj) ma operator logiczny „nie”, który jest wykrzyknikiem (podobnie jak wiele innych języków). Spróbuj tego:źródło
if [ ! \( -f "f1" -a -f "f2" \) ] ; then echo MISSING; fi
if [ ! -f "f1" ] || [ ! -f "f2" ] ; then echo MISSING; fi
[ -f /tmp/foo.txt ] || echo "File not found!"
-e: Returns true value, if file exists
-f: Return true value, if file exists and regular file
-r: Return true value, if file exists and is readable
-w: Return true value, if file exists and is writable
-x: Return true value, if file exists and is executable
-d: Return true value, if exists and is a directory
! -f
z&&
kontra-f
z||
. Ma to związek z kodem wyjścia zwróconym przez kontrolę braku / istnienia. Jeśli potrzebujesz, aby twoja linia zawsze wychodziła czysto z kodem wyjścia 0 (a czasem nie chcesz tego ograniczenia), te dwa podejścia nie są wymienne. Alternatywnie, po prostu użyjif
instrukcji i nie musisz się już martwić kodem wyjścia z kontroli braku / istnienia.Testowanie plików bash
-b filename
- Blokowanie pliku specjalnego-c filename
- Plik znaków specjalnych-d directoryname
- Sprawdzanie istnienia katalogu-e filename
- Sprawdzanie istnienia pliku, niezależnie od typu (węzeł, katalog, gniazdo itp.)-f filename
- Sprawdzanie regularnego istnienia pliku, a nie katalogu-G filename
- Sprawdzanie, czy plik istnieje i jest własnością efektywny identyfikator grupy-G filename set-group-id
- Prawda, jeśli plik istnieje i ma ustawiony identyfikator grupy-k filename
- Bit lepki-L filename
- Łącze symboliczne-O filename
- Prawda, jeśli plik istnieje i jest własnością efektywnego identyfikatora użytkownika-r filename
- Sprawdź, czy plik jest czytelny-S filename
- Sprawdź, czy plik jest gniazdem-s filename
- Sprawdź, czy rozmiar pliku jest różny od zera-u filename
- Sprawdź, czy ustawiony jest bit pliku set-user-id-w filename
- Sprawdź, czy plik jest zapisywalny-x filename
- Sprawdź, czy plik jest wykonywalnyJak używać:
Ekspresja Test może być zniesiona przez pomocą
!
operatoraźródło
-n String
- Sprawdź, czy długość łańcucha nie jest równa zero. Czy masz na myślifile1 -nt file2
- Sprawdź, czy plik 1 jest nowszy niż plik 2 (możesz też użyć opcji -ot dla starszych)The unary operator -z tests for a null string, while -n or no operator at all returns True if a string is not empty.
~ ibm.com/developerworks/library/l-bash-test/index.htmlMożesz zanegować wyrażenie za pomocą „!”:
Odpowiednią stroną podręcznika jest
man test
lub, odpowiednio,man [
-help test
lubhelp [
dla wbudowanego polecenia bash.źródło
[
jest wbudowana. Odpowiednia informacja jest więc uzyskiwana raczej przezhelp [
... ale to pokazuje, że[
jest to synonimtest
wbudowanego, stąd odpowiednia informacja jest uzyskiwana przezhelp test
. Zobacz także sekcję Wyrażenie warunkowe Bash w podręczniku .[
zachowuje się bardzo podobnie do polecenia zewnętrznego[
polecenia, więc alboman test
czyman [
daje dobry pomysł, jak to działa.[
ma więcej przełączników niż polecenie zewnętrzne[
znalezione w moim systemie ... Ogólnie mówiąc, uważam, że lepiej jest przeczytać dokumentację dotyczącą danego narzędzia, a nie dokumentację dotyczącą innego, niejasno powiązanego. Mogę się jednak mylić;)
Możliwe też, że plik jest zepsutym dowiązaniem symbolicznym lub nieregularnym plikiem, takim jak np. Gniazdo, urządzenie lub fifo. Na przykład, aby dodać sprawdzanie uszkodzonych dowiązań symbolicznych:
źródło
Warto wspomnieć, że jeśli chcesz wykonać jedno polecenie, możesz je skrócić
do
lub
źródło
Wolę zrobić następującą linijkę w formacie zgodnym z powłoką POSIX :
Dla kilku poleceń, tak jak zrobiłbym to w skrypcie:
Kiedy zacząłem to robić, rzadko używam już w pełni wpisanej składni !!
źródło
[
albotest
wbudowaną by przetestować dla istnienia plików argumentu domyślnie (w przeciwieństwie do-e
)? Czy nie byłoby to dwuznaczne? AFAIK (i AIUI sekcja „WARUNKOWE WYRAŻENIA”), jedyną rzeczą, która jest testowana z podejścia jest to, że argument nie jest pusty (lub nieokreślony), który jest w tym przypadku tautologią (niech$DIR = ''
a$FILE = ''
, to argument jest nadal'//'
).ls /foo
wynikls: cannot access /foo: No such file or directory
.[ /foo ] && echo 42
wynik42
. GNU bash, wersja 4.2.37 (1) -release (i486-pc-linux-gnu).-f
opcji, w chwili pisania tej odpowiedzi. Oczywiście zawsze możesz użyć-e
, jeśli nie jesteś pewien, czy będzie to zwykły plik. Dodatkowo we wszystkich moich skryptach cytuję te konstrukcje, musiałem to właśnie przesłać bez odpowiedniego potwierdzenia.[ $condition ] && if_true || if_false
jest podatna na błędy. W każdym razie[ ! -f "$file" ] && if_not_exists
łatwiej mi je przeczytać i zrozumieć niż[ -f "$file" ] || if_not_exists
.Aby przetestować istnienie pliku, parametrem może być dowolny z poniższych:
Wszystkie poniższe testy dotyczą zwykłych plików, katalogów i dowiązań symbolicznych:
Przykładowy skrypt:
źródło
Możesz to zrobić:
lub
Jeśli chcesz sprawdzić zarówno plik, jak i folder, użyj
-e
opcji zamiast-f
.-e
zwraca true dla zwykłych plików, katalogów, gniazd, znaków specjalnych, blokowania plików specjalnych itp.źródło
[
użytecznością.-f
) i katalogi to tylko dwa z wielu różnych typów plików . Istnieją również gniazda, dowiązania symboliczne, urządzenia, fifos, drzwi ...[ -e
sprawdzą istnienie pliku (dowolnego typu, w tym zwykły, fifo, katalog ...) po rozwiązaniu symlink .-e
, on potrzebuje-f
.Należy zachować ostrożność podczas uruchamiania
test
zmiennej niecytowanej, ponieważ może ona generować nieoczekiwane wyniki:Zazwyczaj zaleca się otoczenie testowanej zmiennej podwójnymi cudzysłowami:
źródło
[ ... ]
.Można to zrobić na trzy różne sposoby:
Neguj status wyjścia za pomocą bash (żadna inna odpowiedź nie powiedziała tego):
Lub:
Neguj test w poleceniu testowym
[
(w taki sposób prezentowało większość odpowiedzi wcześniej):Lub:
Działaj na wynik testu ujemny (
||
zamiast&&
):Tylko:
Wygląda to głupio (IMO), nie używaj go, chyba że twój kod musi być przenośny do powłoki Bourne'a (takiej jak
/bin/sh
Solaris 10 lub wcześniejsza), w której brakowało operatora negacji potoku (!
):źródło
! [
i[ !
?! [
Jest POSIX dla rurociągów osłonowych 2.9.2 (dowolny poleceń)Otherwise, the exit status shall be the logical NOT of the exit status of the last command
i[ !
jest POSIX dla testu! expression True if expression is false. False if expression is true.
Więc oba są POSIX, w moim doświadczeniu, oba są szeroko obsługiwane.!
słowa kluczowego wprowadzonego przez powłokę Korna. Jednak z wyjątkiem Solaris 10 i starszych, prawdopodobnie nie spotkasz się teraz z powłoką Bourne'a.W
[
komenda robistat()
(nielstat()
) wywołanie systemowe na ścieżce przechowywanej w$file
i zwraca prawda jeśli się powiedzie, że wywołanie systemowe i typ pliku jako zwrócony przezstat()
to „ regular ”.Więc jeśli
[ -f "$file" ]
zwróci true, możesz powiedzieć, że plik istnieje i jest zwykłym plikiem lub dowiązaniem symbolicznym, które ostatecznie przekształca się w zwykły plik (lub przynajmniej tak było w momenciestat()
).Jeśli jednak zwraca false (lub jeśli
[ ! -f "$file" ]
lub! [ -f "$file" ]
zwraca true), istnieje wiele różnych możliwości:stat()
wywołanie systemowe może zakończyć się niepowodzeniem.Krótko mówiąc, powinno to być:
Aby mieć pewność, że plik nie istnieje, potrzebujemy
stat()
wywołania systemowego z kodem błęduENOENT
(ENOTDIR
mówi nam, że jeden ze składników ścieżki nie jest katalogiem, to kolejny przypadek, w którym możemy stwierdzić, że plik nie istnieje istnieje przy tej ścieżce). Niestety[
polecenie to nas nie informuje. Zwróci false, czy kod błędu to ENOENT, EACCESS (odmowa zgody), ENAMETOOLONG lub cokolwiek innego.[ -e "$file" ]
Test może być również wykonane zls -Ld -- "$file" > /dev/null
. W takim przypadkuls
powie Ci, dlaczegostat()
nie powiodło się, chociaż informacji nie można łatwo wykorzystać programowo:Przynajmniej
ls
mówi mi, że to nie dlatego, że plik nie istnieje, że zawodzi. Jest tak, ponieważ nie można stwierdzić, czy plik istnieje, czy nie.[
Komenda prostu zignorował problem.Za pomocą
zsh
powłoki można wyszukać kod błędu za pomocą$ERRNO
specjalnej zmiennej po nieudanym[
poleceniu i zdekodować tę liczbę za pomocą$errnos
specjalnej tablicy wzsh/system
module:(uwaga:
$errnos
obsługa została zerwana z niektórymi wersjamizsh
po zbudowaniu z najnowszymi wersjamigcc
).źródło
Aby odwrócić test, użyj „!”. Jest to równoważne operatorowi logicznemu „nie” w innych językach. Spróbuj tego:
Lub napisane w nieco inny sposób:
Lub możesz użyć:
Lub wyciskając wszystko razem:
Które można zapisać (używając wtedy „i” operator: &&) jako:
Który wygląda tak krócej:
źródło
To też
test
może się liczyć. To zadziałało dla mnie (w oparciu o Bash Shell: Check File Exists or Not ):źródło
Ten kod również działa.
źródło
Najprostszy sposób
źródło
Ten skrypt powłoki działa również w celu znalezienia pliku w katalogu:
źródło
read -p "Enter file name: " -r a
do monitowania, jak i czytania. Używa cudzysłowów wokół zmiennej; to dobrze, ale należy to wyjaśnić. Może być lepiej, jeśli powtórzy nazwę pliku. I to sprawdza, czy plik istnieje i nie jest pusty (to jest znaczenie-s
), podczas gdy pytanie dotyczy dowolnego pliku, pustego lub nie (dla czego-f
bardziej odpowiednie).czasami przydatne może być użycie && i || operatorzy.
Jak w (jeśli masz polecenie „test”):
lub
źródło
Jeśli chcesz użyć
test
zamiast[]
, możesz użyć,!
aby uzyskać negację:źródło
Możesz również pogrupować wiele poleceń w jednym wierszu
[ -f "filename" ] || ( echo test1 && echo test2 && echo test3 )
lub
[ -f "filename" ] || { echo test1 && echo test2 && echo test3 ;}
Jeśli nazwa pliku nie zostanie zakończona, wynikiem będzie
Uwaga: (...) działa w podpowłoce, {...;} działa w tej samej powłoce.
Notacja w nawiasach klamrowych działa tylko w trybie bash.źródło