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?


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.


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.


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

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.


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.


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.


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.


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.


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

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

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.


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ść.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.