Usuń plik, ale tylko jeśli jest to dowiązanie symboliczne


11

Idealnie chciałbym takie polecenie

rm --only-if-symlink link-to-file

ponieważ spaliłem się zbyt wiele razy przypadkowo usuwając plik zamiast dowiązania symbolicznego wskazującego na plik. Może to być szczególnie złe, gdy zaangażowane jest sudo. Teraz oczywiście robię to, ls -alaby upewnić się, że naprawdę jest to dowiązanie symboliczne i takie, ale jest podatne na błąd operatora (podobnie nazwany plik, literówka itp.) I warunki wyścigu (jeśli ktoś z jakiegoś powodu chciał mnie usunąć). Czy jest jakiś sposób, aby sprawdzić, czy plik jest dowiązaniem symbolicznym i usunąć go tylko, jeśli jest w jednym poleceniu?


1
Nie sądzę, że wyścig powinien być problemem. Każdy, kto byłby w stanie usunąć dowiązanie symboliczne i zastąpić go plikiem, musiałby mieć uprawnienia do zapisu w katalogu, co oznacza, że ​​mógłby również sam usunąć plik.
Nate Eldredge

Odpowiedzi:


19
 $ rm_if_link(){ [ ! -L "$1" ] || rm -v "$1"; }

 #test
 $ touch nonlink; ln -s link
 $ rm_if_link nonlink
 $ rm_if_link link
   removed 'link'     

4
Z pewnością łatwiej byłoby usunąć !i zmienić ||na&&
glenn jackman

5
@glennjackman Przyzwyczaiłem się preferować ||formę. &&obniża poziom, jeśli jesteś w set -etrybie.
PSkocik

@PSkocik Zasadniczo jest to ryzykowne, ponieważ nie rozróżnia interesującego przypadku (plik istnieje i jest dowiązaniem symbolicznym) oraz innych przyczyn niezerowego kodu wyjścia, takich jak pusta niecytowana wartość ( [ ! -L $1 ]), przy użyciu niepoprawnego operatora ( [ ! -l foo ]), a nawet błąd składniowy ( [ ! -q foo || echo foo)
l0b0

2
@XiongChiamiov Problem rm_if_link(){ [ -L "$1" ] && rm -v "$1"; }polega na tym, że uruchomienie go w set -e trybie bez dowiązania zabije proces powłoki. Możesz dołączyć, || :ale wtedy staje się, IMHO, jeszcze mniej wyraźne niż ! ||wersja, i zapobiegnie to rmzabiciu cię przez niepowodzenie set -e, co jest prawdopodobnie niepożądane. ! ||jest dość zwięzły i jasny i nie cierpi na żaden z tych problemów.
PSkocik

1
Nope . Inne opcje: a) umieść rmtest w swoim wnętrzu, b) użyj rzeczywistej instrukcji if, c) nie chodź za pomocą -ewewnętrznych interaktywnych powłok (i przetestuj swoje skrypty!). Jeśli chcesz spierać się o czytelność, skorzystanie ifz testu, czy coś jest linkiem, jest wyraźnie zwycięzcą.
Bojkot SE dla Moniki Cellio

5

Można użyć find, a jego -type lstan testu (który sprawdza, jeśli okazało się, że obiekt jest l atrament lub nie)

Na przykład, jeśli masz plik o nazwie foow bieżącym katalogu, możesz to zrobić:

$ find . -type l -iname "foo" -delete

Możesz to uprościć za pomocą:

$ find . -maxdepth 1 -type l -delete

Co spowoduje usunięcie wszystkich dowiązań symbolicznych w bieżącym katalogu.

Ostrzeżenie:

-deleteOpcja w findto naprawdę bardzo niebezpieczne. UPEWNIJ SIĘ, ŻE UMIESZCZASZ NA KOŃCU ZNAJDUJĄCEGO POLECENIA Jeśli go zgubisz, usunie wszystko, co znajdzie, niezależnie od tego, czy wyniki są zgodne z twoim warunkiem.

Jak sugerowano w komentarzach, bezpieczniejszą opcją może być użycie findi rm -i(co zmusza do potwierdzenia usunięcia pliku) w połączeniu:

$ $ find . -type l -iname "foo" | xargs rm -i

Osobiście używam -exec trash {} \;do tymczasowego usuwania plików, ponieważ ja, podobnie jak ty, zostałem spalony rmw przeszłości. Podwójnie oznacza źle umieszczoną -deleteflagę.

http://slackermedia.ml/trashy


1
Zamiast -delete możesz po prostu wydrukować go i przekazać do xargs: find . -type l -iname "foo" | xargs rm -i jest bezpieczniej.
Boban P.

1
Na pewno podoba mi się użycie @ BobanP rm -idla bezpieczeństwa.
Klaatu von Schlacker,

3
„Spowoduje to usunięcie wszystkich dowiązań symbolicznych w bieżącym katalogu” ... i dowolnego punktu poniżej.
Joseph R.

1
Jako @JosephR. powiedział, że pójdzie całą drogę. Dodaj -maxdepth 1 w find.
Boban P.

1
Nadal łamie nazwy plików spacjami. Zaproponuj użycie -print0for findi -0for xargs.
Wildcard

4
zsh -c 'rm foo(@)'

@jest kwalifikatorem globalnym ; wzór foo(@)pasuje do tego foo, co pasuje, ale tylko do dowiązań symbolicznych.

foo(-@)pasowałyby tylko zepsute dowiązania symboliczne foo(@,L0)pasowałyby tylko dowiązania symboliczne i puste pliki.

Oczywiście, jeśli korzystasz z ZHS, po prostu musisz wpisać rm foo(@). Trzeba uważać, aby nie naciskać Enterprzed pisaniem (@).


1
Zsh brzmi coraz mocniej, gdy widzę takie odpowiedzi.
Jeff Schaller
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.