skrypt powłoki, aby usunąć plik, jeśli już istnieje

183

Pracuję nad niektórymi rzeczami, w których przechowuję dane w pliku. Ale za każdym razem, gdy uruchamiam skrypt, zostaje on dołączony do poprzedniego pliku.

Chcę uzyskać pomoc w usunięciu pliku, jeśli już istnieje.

Niks
źródło
3
Sprawdź, czy plik istnieje ... a następnie zadzwoń rm $my_file, prawda? Jakiej powłoki używasz?
Chris Sprague,

Odpowiedzi:

184

Nie zawracaj sobie głowy sprawdzaniem, czy plik istnieje, po prostu spróbuj go usunąć.

rm -f /p/a/t/h
# or
rm /p/a/t/h 2> /dev/null

Zauważ, że drugie polecenie zakończy się niepowodzeniem (zwróci niezerowy status wyjścia), jeśli plik nie istniał, ale pierwsze odniesie sukces dzięki opcji -f(skrót od --force). W zależności od sytuacji może to być ważny szczegół.

Ale bardziej prawdopodobne jest, że jeśli dołączasz się do pliku, dzieje się tak dlatego, że Twój skrypt >>przekierowuje coś do pliku. Wystarczy wymienić >>z >. Trudno powiedzieć, ponieważ nie podałeś kodu.

Pamiętaj, że możesz zrobić coś takiego test -f /p/a/t/h && rm /p/a/t/h, ale jest to całkowicie bezcelowe. Jest całkiem możliwe, że test zwróci wartość true, ale / p / a / t / h nie będzie istniał przed próbą jego usunięcia, lub gorzej test zakończy się niepowodzeniem i / p / a / t / h zostanie utworzony przed wykonaniem następnego polecenia, które oczekuje, że nie będzie istnieć. Próba tego jest klasycznym warunkiem wyścigu. Nie rób tego

William Pursell
źródło
5
Nie jest to pomocne, jeśli muszą wiedzieć, czy istniał i został usunięty. Jedzenie stderr tego nie zapewnia. Brak obsługi istnienia nie pozwala na szersze uruchomienie skryptu bez niepowodzenia.
uchuugaka
@uchuugaka To proste rozwiązanie, gdy nie obchodzi Cię, czy plik tam jest, wszystko, czego chcesz, to upewnić się, że go nie ma.
Lukas Liesis
Nadchodzące dobre odpowiedzi powinny być wyczerpujące, a efektem ubocznym jest uogólnienie mojej wiadomości, ale skrypty powłoki często chcą wiedzieć, co znajduje się, a czego nie, a co jest lub nie.
uchuugaka
rm /p/a/t/h 2> /dev/nullnie zachowa kodu powrotu ( echo $?) jako 0, jeśli plik nie istnieje. To sprawiłoby, że Jenkins byłby w pewnym sensie niepowodzeniem tylko dlatego, że próbowaliśmy usunąć nieistniejący plik.
ViFI
@uchuugaka - Długo unikałem odpowiedzi na ten komentarz, ale należy się nim zająć. Sprawdzanie, czy plik istnieje przed jego usunięciem, jest zawsze złym pomysłem. Zobacz ostatni akapit mojej odpowiedzi. Istnieje nieodłączny warunek rasowy, którego po prostu nie można uniknąć, robiąc takie rzeczy. Jeśli nie chcesz nadpisywać istniejącego pliku, możesz spróbować magii specyficznej dla powłoki (jak noclobberw bash), lub może przeskoczyć istniejący plik, aby przekierowanie nie powiodło się, jeśli plik istnieje (nie omija warunków wyścigu), ale wystarczy, że błędy będą bardziej subtelne.
William Pursell
127

Innym poleceniem w jednym wierszu jest:

[ -e file ] && rm file
liwp_Stephen
źródło
11
Lub alternatywnie: [! -e plik] || plik rm. Ta wersja zwraca 0 zamiast błędu.
nawfel bgh
@nawfelbgh Dzięki, jest to świetne do łączenia w dłuższe skrypty.
Abe
83

Możesz użyć tego:

#!/bin/bash

file="file_you_want_to_delete"

if [ -f $file ] ; then
    rm $file
fi
Jindra Helcl
źródło
4
To powinna być wybrana odpowiedź.
ingernet
Prosty i łatwy do odczytania, a także zapewnia, że echo $?nie daje 1, jeśli plik nie istnieje.
ViFI
W razie potrzeby możesz to zrobić jako jeden wiersz, patrz moja odpowiedź poniżej.
nbeuchat
65

Jeśli chcesz zignorować krok, aby sprawdzić, czy plik istnieje, czy nie, możesz użyć dość łatwego polecenia, które usunie plik, jeśli istnieje, i nie wyśle ​​błędu, jeśli nie istnieje.

 rm -f xyz.csv
greperror
źródło
1
To tylko kopia części najwyżej ocenianej odpowiedzi z 2015 roku.
sorry
16
główna odpowiedź nie tłumaczyła, że ​​dzięki -ftemu nie rzuci błędu. Ta odpowiedź pomogła mi, dziękuję.
Doug
Zgadzam się z Dougiem, chociaż wydaje się, że jest to dobry przypadek użycia dla edycji odpowiedzi typu wiki.
Philip
16

Skrypt powłoki jednowierszowej, aby usunąć plik, jeśli już istnieje (na podstawie odpowiedzi Jindry Helcl):

[ -f file ] && rm file

lub ze zmienną:

#!/bin/bash

file="/path/to/file.ext"
[ -f $file ] && rm $file
nbeuchat
źródło
13

Coś takiego działałoby

#!/bin/sh

if [ -fe FILE ]
then 
    rm FILE
fi 

-f sprawdza, czy jest to zwykły plik

-e sprawdza, czy plik istnieje

Wprowadzenie do if, aby uzyskać więcej informacji

EDYCJA: -e użyte z -f jest redundantne, dla samego użycia -f też powinno działać

P1kachu
źródło
-ajest przestarzałe, użyj -ezamiast niego.
mziccard,
mój zły, naprawiony. Dzięki @mziccard
P1kachu
spowoduje to błędy w katalogach lub linkach lub innych niestandardowych plikach. Imho jest lepszy / bezpieczniejszy w użyciu -f.
Jindra Helcl
1
dobrze. Mimo to, -ew -fejest zbędna, jak -frównież sprawdza istnienie pliku jako o ile wiem ..
Jindra Helcl
Jeśli
zmienię
4

if [ $( ls <file> ) ]; then rm <file>; fi

Ponadto, jeśli przekierujesz dane wyjściowe, >zamiast >>tego zastąpi poprzedni plik

nLee
źródło
3
przepraszam, ale nie jest to jedna linijka, ale taka jest @liwp_Stephen.
fiorentinoing
Nawet jeśli jest właściwie cytowany, to łamie się, jeśli filejest coś takiego5 -lt 2
William Pursell