2013-11-24 12 views
8

Próbuję uzyskać odpowiednik następującego kodu C w skryptach powłoki.Jak wykonać określone polecenia, jeśli plik NIE istnieje?

if(!exist) { 
    command; 
    command; 
} 
else { 
    command; 
    command; 
} 

Co staram się dokładniej w tym skrypcie powłoki, aby sprawdzić, czy plik nie istnieje, a następnie go utworzyć.

Naprawdę bardzo przepraszam, jeśli jest to duplikat innego pytania, ale naprawdę nie wiedziałem, jak go wyszukać.

+2

Jeśli interesują Cię skrypty basha, bardzo dobrym źródłem informacji jest http://www.tldp.org/LDP/abs/abs-guide.pdf –

+0

Dziękuję, kolego! Cóż, szczerze mówiąc, pomyślałem, że to odpowiednia część Stack Exchange, aby odpowiedzieć na tego rodzaju pytania. –

+2

To jest właściwe miejsce. Twoje pytanie dotyczy tematu, skrypty powłoki @Patrick są jawnie [na temat] (http://unix.stackexchange.com/help/on-topic). Pytania SOFT dotyczące skryptów są bardzo łatwo zgubione w hałasie, możesz zapytać je, gdziekolwiek czujesz się bardziej komfortowo. – terdon

Odpowiedz

14

Można to wykorzystać:

 
if [ ! -e "$file" ]; then 
     touch file 
else 
     ... 
fi 
+0

race-condition-city, czy jest jakiś sposób użycia flagi, np. 'Touch -e file', która kończy się na 1, jeśli plik już istnieje? –

7
if [ ! -e "$path" ] 
then 
    touch -- "$path" 
fi 

Prostsza wersja byłaby po prostu touch -- "$path" - tworzy plik, jeśli nie istnieje, a tylko aktualizuje dostępu i modyfikacji razy, jeśli nie istnieje. double dash (--) zapewnia, że ​​możesz utworzyć plik, nawet jeśli zaczyna się od myślnika, a quotes około $path są konieczne.

+0

Dziękuję bardzo! Nie mogę zaakceptować rozwiązania, ponieważ nie mam wystarczającej reputacji –

16

Sprawdzanie czy plik istnieje, jest bardzo częstym zadaniem. Aby wyszukać odpowiednie pytania, skorzystaj z paska wyszukiwania (w prawym górnym rogu). Mam lots of results z terminami „skrypt bash istnieje”

W każdym razie, chcesz albo test wbudowane lub jego semantyczny odpowiednik [ ]:

[ ! -e your_file ] && >your_file 

lub

test ! -e your_file && >your_file 

który będzie pierwszy test, że your_file nie istnieje (!) istnieje (-e) i tworzy go, jeśli tak jest.

Aby uzyskać więcej informacji na temat różnych testów można uruchomić (inne niż -e), można wpisać:

help -m test | less 
+3

Możesz także użyć oceny zwarcia, jak w '[-e twój_plik] || > Twój plik < – Useless

7

nie rób tego, to nie tylko do wyścigu, ale także [ -e /path/file ] kontrole jeśli możesz zrobić stat(2) w pliku, więc zwróci wartość false z różnych powodów, nie tylko dlatego, że plik nie istnieje.

Przykładem jest dowiązanie symboliczne do pliku, który nie istnieje lub plik w katalogu, do którego nie masz uprawnień do wyszukiwania.

O wiele lepszym sposobem jest użycie odpowiednich flag do wywołania systemowego open(2), czyli O_CREAT|O_EXCL. W ten sposób, open() ulegnie awarii, jeśli plik nie istnieje, bez konieczności sprawdzania kilku milionów taktów zegara procesora wcześniej.

Z Bourne jak powłoki:

if (set -C && : > "$file") 2> /dev/null; then 
    print '%s\n' "$file has been created 
else 
    print '%s\n' "It hasn't, possibly because it was already there" 
fi 

(set -C jest umożliwienie flagę O_EXCL).

Ponadto, dlaczego chcesz utworzyć pusty plik? Prawdopodobnie chcesz zapisać coś w tym pliku.Następnie, po prostu to zrobić:

set -C 
{ 
    echo blah 
    other-commands that-generate-the-content 
} > "$file" 

następnie, że grupa komenda jest wykonywana tylko wtedy, gdy file nie istnieje (a było to możliwe, aby go utworzyć).

Jeśli chcesz przetestować dla istnienia pliku, zapisz go co najmniej:

[ -e "$file" ] || [ -L "$file" ] 

lub

ls -d -- "$file" > /dev/null 2>&1 

jeśli dbają o to potencjalnie jest dowiązaniem symbolicznym. To nadal zwróci wartość false, jeśli plik istnieje, ale nie masz uprawnień do jego weryfikacji.


Teraz, jeśli chcesz dłużej i odpowiedzi na temat badań historycznych dla istnienia pliku:

Początkowo komenda test (w Unix V7, gdzie po raz pierwszy pojawił) had no -e (nor -h/-L option or -a unary) opcja.

Sposób testowania istnienia pliku był zgodny z ls. ls (z -d) wyświetla listę plików i zgłasza błąd (i zwraca kod zakończenia false), jeśli nie może wyszukać pliku z jakiegoś powodu. Początkowo uniks nie zawierał dowiązań symbolicznych, ale po ich wprowadzeniu zmieniono ls, aby uzyskać plik lstat(2) zamiast pliku stat(2). Oznacza to, że w przypadku dowiązania symbolicznego ls zwraca informacje o samym pliku symlink, a nie o pliku na ścieżce, do której wskazuje dowiązanie symboliczne.

Opcja do test (aka [) do testowania dla pliku „istnienie” wprowadzono po raz pierwszy w Korn shell test builtin. To był -a, a nie -e. -a jest dla dostępny (uważam), który jest bardziej dokładny termin niż istniejących.

Nie wiem, kiedy lub co wprowadzono -e, ewentualnie POSIX. POSIX says, który został wybrany pod numer pod numerem -a w celu uniknięcia ewentualnego pomyłki z operatorem binarnym (dla i).

W każdym przypadku zarówno -a, jak i -e wypróbują w pliku stat(2), a nie lstat(2). Czyli:

[ -e "$file" ] 

odpowiada:

ls -Ld -- "$file" > /dev/null 2>&1 

Tak, ściśle rzecz biorąc, to zwraca wartość true, jeżeli w czasie badanie zostało zrobione, to było możliwe do wyszukiwania ścieżki po rozwiązywaniu dowiązania , a jeśli nie powiedzie się stat(2), przyczyna niepowodzenia zostanie zignorowana.

stat może zakończyć się niepowodzeniem, jeśli plik nie istnieje (ENOENT), to znaczy, jeśli plik nie istnieje lub istnieje ale jest dowiązaniem do pliku, który nie istnieje, ale także wiele innych powodów.Patrząc na the possible error codes of stat(2) daje kilka pomysłów:

  • EACCESS: Podczas uchwałą ścieżki (i to może być każdy składnik ścieżki i w drodze jakiegokolwiek dowiązania symbolicznego), nie masz wyszukiwarki zgodę na jednym katalogu składnik (pamiętaj, że możesz nadal mieć dostęp do pliku inną ścieżką).
  • ELOOP: niemożliwe jest rozwiązanie ścieżki, ponieważ zbyt wiele dowiązań symbolicznych zostało rozwiązanych, aby się tam dostać.
  • ENOTDIR. Na przykład na /etc/passwd/foo lub dowiązanie symboliczne do niego.
+1

Zgłoszenie roszczenia do wyścigu jest przedwczesne. OP nie określił, skąd pochodzi ten plik i jest możliwe, że skrypt jest jedyną rzeczą, która go tworzy. Również mówienie, że '[-e/path/file]' nie powinno być używane, ponieważ może niepoprawnie zawieść, nie jest dobrym argumentem. Jeśli test nieprawidłowo zakończy się niepowodzeniem i spróbuje utworzyć plik, błąd tworzenia zostanie zgłoszony. Po usunięciu testu i użyciu O_EXCL błąd utworzenia zostanie wygenerowany z dokładnie tego samego powodu, co test. Plus może to być program, który tworzy plik, w którym 'set -C' nie uniemożliwi nadpisania programu. – Patrick

+1

@Patrick. Nie, jeśli plik jest dowiązaniem symbolicznym do nieistniejącego pliku w istniejącym katalogu, '[-e" $ plik "]' zwróci false, tworzenie zakończy się sukcesem bez O_EXCL (gdzie jest to niebezpieczne, ponieważ atakujący może zmusić cię do utworzenia pliki, których nie chcesz), i zawiedzie z O_EXCL (co oznacza, że ​​nie musisz tego robić). –

+0

Również może być bardzo "przedwczesne" dla OP. Może się zdarzyć, że uruchamia on tylko jedną instancję skryptu na raz, że nic innego nie może zapisywać w tym pliku, że plik jest w bardzo spokojnym obszarze, do którego tylko jeden użytkownik ma dostęp do zapisu, i że ten użytkownik nigdy nie jest zaangażowane w radzenie sobie z "obcymi/obcymi/niekontrolowanymi" danymi, ale na stosie, odpowiedzi są przeznaczone dla wszystkich, więc IMO, należy wskazać na ryzyko. Biorąc pod uwagę, że metoda ta jest bezpieczniejsza i tańsza (tylko jedno wywołanie systemowe, chociaż widelec pierwszy, bez zewnętrznego polecenia), metoda powinna być preferowana. –

Powiązane problemy