Jak sprawić, aby rm nie wyświetlał błędu, jeśli plik nie istnieje?

329

Piszę plik makefile, który wyczyści niektóre bezużyteczne pliki na końcu kompilacji. Jeśli cel został już utworzony, oczywiście pominie go, a zbędnego pliku może nie być. Więc jeśli to zrobię:

rm lexer.ml interpparse.ml interpparse.mli

Mogę wyświetlać błędy, ponieważ jeden z plików nie istnieje. Czy jest jakiś sposób rmna zignorowanie tych plików?

Podczas czytania strony podręcznika widzę następującą opcję:

 -f          Attempt to remove the files without prompting for confirma-
             tion, regardless of the file's permissions.  If the file does
             not exist, do not display a diagnostic message or modify the
             exit status to reflect an error.  The -f option overrides any
             previous -i options.

To brzmi prawie tak, jak chcę, ale tak naprawdę nie jestem pewien co do części dotyczącej uprawnień. Czy jest na to sposób?

Jason Baker
źródło
Próbowałeś trochę rmw piaskownicy? Wygląda na to, że -frobi dokładnie to, co chcesz, niezależnie od globowania.
JMD
Jeśli uprawnienia na to nie zezwalają, rm będzie -fnadal próbował je usunąć. To zawiedzie. Nie powie ci, że to się nie udało. Przydatne, jeśli nazwa pliku to zmienna lub glob.
LawrenceC
tylko dla kompletności: istnieje rm --interactive=nevertakie działanie, rm -fz wyjątkiem tego, że zwraca status wyjścia błędu. zobacz tutaj po więcej szczegółów: unix.stackexchange.com/questions/72864/…
lesmana

Odpowiedzi:

282

Ta -fopcja jest zdecydowanie tym, czego chcesz używać.

Potwierdzenie uprawnień do plików, do których się odnosi, jest następujące:

$ touch myfile    
$ chmod 400 myfile
$ rm myfile       
rm: remove write-protected regular empty file `myfile'?

Więc rmostrzeże Cię, jeśli spróbujesz usunąć plik nie masz uprawnień do zapisu na. Jest to dozwolone, jeśli masz uprawnienia do zapisu w katalogu, ale jest to trochę dziwne, dlatego rmzwykle ostrzega o tym.

Dave Webb
źródło
1
Większość, ale nie wszystkie systemy zapytają (tak myślę). Niektóre wymagają -i.
DaveParillo
1
Jeśli chcesz komunikat o błędzie, ale nie kod wyjścia błędu, zobacz odpowiedź Giel Berkers . Używam set -ewe wszystkich moich skryptach bash, aby skrypt zakończył działanie po wystąpieniu błędu dowolnego polecenia. Często chcę, aby skrypt informował mnie rmo błędzie, ale i tak kontynuuję. trwa.
cledoux,
124

Innym rozwiązaniem jest to: https://stackoverflow.com/questions/11231937/bash-ignoring-error-for-a-particular-command

Wystarczy dodać polecenie OR po swoim poleceniu:

rm -rf my/dir || true

W ten sposób, gdy instrukcja nr 1 zawiedzie (wyrzuca błąd), uruchom instrukcję nr 2, która jest po prostu true.

Giel Berkers
źródło
4
Drukuje błąd i kontynuuje wykonywanie, które było pożądane w moim przypadku.
worldsayshi
9
Albo rm -rf my/dir ||:jeszcze bardziej zwięźle ( :skrót true)
Godsmith
Moim zdaniem lepsze rozwiązanie. Jest łatwo widoczne, co się dzieje i dlaczego kod wynikowy jest ignorowany. Lubię to!
Mavamaarten
76

Jestem spóźniony na imprezę, ale używam tego cały czas. W makefile dodaj -na początku linii, aby zignorować wartość zwracaną przez tę linię. Tak jak:

-rm lexer.ml interpparse.ml interpparse.mli
Robert Li
źródło
9
Nadal jednak wypisuje na konsoli błąd, który uczy, jak ignorować błędy w wyjściu make, co prawdopodobnie nie jest tym, czego chcesz. rm -rf jest moim zdaniem lepszą opcją.
Godsmith,
@Godsmith Wolę zignorować błąd niż wymuszać rekurencyjne usuwanie. To może być bardzo niegrzeczne. I +1 za specyficzną składnię makefile
Daishi
Jeśli rm -rf może być „niegrzeczny”, oznacza to, że używasz make poza katalogiem pod kontrolą wersji. Dlaczego?
Godsmith,
Proszę podać link do dokumentacji. Mógł znaleźć opis tej funkcji.
George Sovetov
14

Jeśli nie chcesz używać opcji -f, alternatywą jest:

rm filethatdoesntexist 2> /dev/null 

To po prostu zapobiegnie drukowaniu błędów.

użytkownik135299
źródło
9
Niestety nadal będzie to dawać kod wyjścia błędu.
Shaun McDonald,
8

Jeśli znajdziesz sposób na zgranie nazw plików, rmnie będziesz narzekać, jeśli nie będzie w stanie znaleźć dopasowania. Więc coś takiego lexer.m* interpparse.*, itp. Powinno działać na ciebie (uważaj, aby nie usunąć zbyt wiele, oczywiście). Ponadto -fjest to całkowicie rozsądna droga, o ile nie masz nadziei, że uprawnienia do plików uratują cię przed usunięciem pliku, którego nie chciałeś - jeśli nie chcesz go usunąć, nie umieszczaj go na liście.

Nick Bastin
źródło
Globowanie byłoby wykluczone, ponieważ istnieje plik lexer.mll, którego nie chcę usunąć. Dzięki za pokazanie, dlaczego -f jest rozsądny. Podejrzewam, że jestem zbyt ostrożny po zbyt wielu wprowadzeniu w błąd sudo rm -rf.
Jason Baker
Nawet bardziej restrykcyjny lexer.m?...? To by złapało lexer.mli lexer.mz, ale nie lexer.mlllub lexer.mla.
JMD
1
@JMD: Przypuszczam, że zależy to od twojej powłoki i tego, jakie wsparcie dopasowania wzorców oferuje dla globowania.
Nick Bastin
6

Opcja -f oznacza, że ​​nie pojawi się monit, jeśli coś nie jest zgodne z oczekiwaniami. Nie oznacza to, że uprawnienia nie są brane pod uwagę.

Jeśli nie masz wystarczających uprawnień do usunięcia pliku, nie zostanie on usunięty.

ALE , jeśli masz wystarczające uprawnienia do zmiany uprawnień, plik zostanie usunięty. Jest tak w przypadku, gdy jesteś właścicielem pliku z uprawnieniami tylko do odczytu dla właściciela (-r --------). Jako właściciel możesz chmod u+w, a następnie usunąć: rm -fusunie ten plik.

mouviciel
źródło
5

Może może pomóc linia podobna do:

touch fakefile.exe fakefile.o && rm *.o *.exe

Wiem, że to nie jest zbyt mądre, ale spełnia swoje zadanie.

Bogdan
źródło
3

Alternatywa:

RmIfIsFile() {  for f in "$@"; do [ -f $f ] && rm $f; done; };  RmIfIsFile lexer.ml interpparse.ml interpparse.mli

Szkoda, że ​​Makefile nie mogą współdzielić definicji funkcji powłoki między wierszami.

reinierpost
źródło
Czy próbowałeś użyć \ (ukośnik odwrotny) na końcu wiersza, aby móc kontynuować w następnym?
jakieś
@some: Tak, można je rozłożyć na wiele wierszy, ale aby udostępnić je w różnych przepisach, musisz umieścić definicję w zmiennej make.
reinierpost
3

Oto, czego używam w skryptach powłoki. Ukrywa komunikat o błędzie i kod błędu.

rm doesnotexist 2> /dev/null || echo > /dev/null
teh_senaus
źródło
co rm doesnotexist 2&> /dev/null
powiesz na
1

możesz dotknąć plików przed ich zapisaniem. które by je stworzyły, gdyby nie istniały :-)

touch lexer.ml interpparse.ml interpparse.mli
rm lexer.ml interpparse.ml interpparse.mli
pospolity
źródło
1

napisz rm -rf ppp>/dev/null 2>&1 nowszy komunikat o błędzie Wystąpił problem, jeśli błąd nie generuje STDERR 2, ale STDOUT 1 ... Dzieje się tak, gdy polecenie nie generuje błędu, ale ostrzeżenie. Musisz ustawić filtr i usunąć tę wiadomość. Ale ta sprawa jest zwyczajna.

Anatolij
źródło
1

sprawdź, czy plik istnieje najpierw, a jeśli tak, to przekaż go do rm. Wtedy błędy z rm będą miały znaczenie. -f lub zignorowanie komunikatu o błędzie zazwyczaj obejmuje więcej niż to, czego chce osoba. -f może robić rzeczy, których nie chcesz robić.

if [ -f lexer.ml ]; then
  rm lexer.ml
fi

dodaj więcej klauzul testowych, jeśli istnieje więcej plików, które chcesz mieć pewność.


źródło