Czuję, że powinienem wiedzieć na pewno: jeśli to zrobię ls <something>
, rm <something>
usunę dokładnie te same ls
wyświetlane pliki ? Czy są jakieś okoliczności, w których rm
można usunąć pliki, które ls
nie były wyświetlane? (To jest w bash 18.04)
Edycja: dziękuję wszystkim, którzy odpowiedzieli. Myślę, że pełna odpowiedź jest kombinacją wszystkich odpowiedzi, więc zaakceptowałem najbardziej uprzywilejowaną odpowiedź jako „odpowiedź”.
Nieoczekiwane rzeczy, których nauczyłem się po drodze:
ls
nie jest tak prosty, jak mogłoby się wydawać, jeśli chodzi o obsługę argumentów- W prostej nieskrępowanej instalacji Ubuntu aliasy .bashrc
ls
- Nie nadawaj nazw plikom zaczynającym się od myślnika, ponieważ mogą one wyglądać jak argumenty poleceń, a nazywanie jednego -r wymaga tego!
rm
nie ma--dry-run
flagi ...find -delete
być lepsze niżrm
? Mówisz „właśnie dlatego” , ale nie jest dla mnie całkowicie jasne, do czego to się odnosi. Zauważ też, że twojefind
wywołanie usunie rekursywnie wszystkie pliki w bieżącym katalogu,rm
a po prostu usunie pliki z katalogu bezpośredniego. To także-name *
nie ma możliwości. Podsumowując, jestem dość zaskoczony twoją radą ...find
jest taka, że możesz ją uruchomić, zobaczyć wszystkie pliki, a następnie uruchomić to samo polecenie-delete
. Ponieważ już widziałeś wynikifind
, nie powinno być dwuznaczności co do tego, co zostanie usunięte (tak naprawdę chciałbym usłyszeć więcej szczegółów na ten temat w formie odpowiedzi)-delete
" - Ale jak to jest lepsze niż uruchamianiels <filespec>
, a następnierm <filespec>
(co OP już wie, jak to zrobić)?find ... -print
najpierw, aby potwierdzić, które pliki zostaną usunięte, a następniefind ... -delete
nadal będziesz usuwać pliki utworzone między dwoma poleceniami. Jeśli użyjesz obu z nich,-print
a-delete
nie otrzymasz potwierdzenia, tylko raport po fakcie o tym, co zostało usunięte (i równie dobrze możesz użyćrm -v
).Odpowiedzi:
Cóż, zarówno
ls
irm
działać na argumentach, które są przekazywane do nich.Te argumenty mogą być plik prosty, więc
ls file.ext
irm file.ext
działają na tym samym pliku, a wynik jest jasne (lista plik / usuń plik).Jeśli zamiast argumentem jest katalog,
ls directory
zawiera wykaz zawartości katalogu, gdyrm directory
nie będzie działać jak jest (czylirm
bez flagi nie można usunąć katalogi, a jeśli nierm -r directory
, to rekurencyjnie usuwa wszystkie pliki mocydirectory
i samego katalogu ).Należy jednak pamiętać, że argumenty wiersza poleceń mogą być poddawane rozszerzeniu powłoki , więc nie zawsze jest gwarantowane, że te same argumenty są przekazywane do obu poleceń, jeśli zawierają symbole wieloznaczne, zmienne, dane wyjściowe z innych poleceń itp.
Jako skrajny przykład pomyśl
ls $(rand).txt
irm $(rand).txt
, argumenty są „takie same”, ale wyniki są zupełnie inne!źródło
ls
vsrm *
gdzie istnieją „ukryte” (kropka) plików, choć nawet to nie jest w ogóle porównania godziwej nie pisałemls *
. Alerm
samo w sobie jest bez znaczenia, więc tak naprawdę to jabłka i pomarańcze. Jeśli dobrze zrozumiałem, to jest sedno twojej odpowiedzi, więc dobra robota :)ls
żyworm -r
: komendals <directory>
nie pokaże ukryte pliki w katalogu, alerm -r <directory>
będzie usuwać nawet ukryte pliki.ls
nie wyświetli ich (chyba że jest to aliasls -a
) irm *
nie usunie ich (chyba żedotglob
ustawiłeś).Jeśli myślisz o czymś takim jak
ls foo*.txt
vs.rm foo*.txt
, to tak, będą wyświetlać i usuwać te same pliki. Powłoka rozszerza glob i przekazuje go do danego polecenia, a polecenia działają na wymienionych plikach. Jeden je wymienia, jeden je usuwa.Oczywista różnica polega na tym, że jeśli którykolwiek z tych plików byłby katalogiem,
ls
wyświetlałby jego zawartość, alerm
nie usunąłby go. Zwykle nie stanowi to problemu, ponieważrm
usunąłby mniej niż to, co pokazałls
.Dużym problemem tutaj jest uruchomienie
ls *
lubrm *
w katalogu zawierającym nazwy plików zaczynające się od myślnika . Oni poszerzyć do linii poleceń tych dwóch programów, jeśli napisał je sam, als
weźmie-r
w znaczeniu „odwrotny porządek”, podczas gdyrm
weźmie-r
oznaczać rekurencyjnego usunięcia. Różnica ma znaczenie, jeśli masz podkatalogi o głębokości co najmniej dwóch poziomów. (ls *
pokaże zawartość katalogów pierwszego poziomu, alerm -r *
wszystko też przekroczy pierwszy poziom ).Aby tego uniknąć, napisz permisywne globusy ze znakiem wiodącym,
./
aby wskazać bieżący katalog i / lub umieść a,--
aby zasygnalizować zakończenie przetwarzania opcji przed globem (tj.rm ./*
Lubrm -- *
).W przypadku globu
*.txt
nie jest to w rzeczywistości problemem, ponieważ kropka jest niepoprawnym znakiem opcji i spowoduje błąd (dopóki ktoś nie rozwinie narzędzi, aby wymyślić dla niego znaczenie), ale mimo to bezpieczniej jest go./
tam umieścić .Oczywiście możesz również uzyskać różne wyniki dla tych dwóch poleceń, jeśli zmienisz opcje globowania powłoki lub utworzysz / przeniesiesz / usunąłeś pliki między poleceniami, ale wątpię, czy miałeś na myśli któryś z tych przypadków. (Radzenie sobie z nowymi / przeniesionymi plikami byłoby wyjątkowo nieuporządkowane.)
źródło
Pomijając powłoki zachowanie, skupmy się tylko to, co
rm
ils
może zajmować się sobą. Co najmniej jeden przypadek, w którymls
pokaże to, czegorm
nie można usunąć, obejmuje uprawnienia do katalogu, a drugi - specjalne katalogi.
i..
.Uprawnienia do folderów
rm
jest operacją na katalogu, ponieważ usuwając plik, zmieniasz zawartość katalogu (lub innymi słowy listę wpisów do katalogu, ponieważ biblioteka jest niczym więcej niż listą nazw plików i i-węzłów ). Oznacza to, że potrzebujesz uprawnień do zapisu w katalogu. Nawet jeśli jesteś właścicielem pliku , bez uprawnień do katalogu nie możesz usunąć plików. Odwrót :rm
można usunąć pliki, które mogą być posiadane przez innych, jeśli właściciel katalogu.Więc możesz bardzo dobrze mieć uprawnienia do odczytu i wykonywania katalogu, które pozwolą ci na przykład przeglądać katalog i przeglądać zawartość w porządku
ls /bin/echo
, ale nie możesz,rm /bin/echo
chyba że jesteś właścicielem/bin
lub podnosić swoje uprawnieniasudo
.Wszędzie zobaczysz takie przypadki. Oto jeden taki przypadek: https://superuser.com/a/331124/418028
Katalogi specjalne ”. i '..'
Innym szczególnym przypadkiem jest
.
i..
katalogów. Jeśli to zrobiszls .
lubls ..
, z przyjemnością pokaże ci zawartość, alerm
ich udostępnianie jest niedozwolone:źródło
Jeśli wpiszesz
ls *
a następnierm *
, możliwe będzie usunięcie więcej plików niżls
pokazał - mogą one zostały stworzone w maleńkim przedziale czasowym pomiędzy końcemls
a początkiemrm
.źródło
/tmp
, w którym wiele aplikacji może tworzyć pliki tymczasowe, więc zawsze jest to możliwe w obu poleceniach za pomocą*
. Jednak niektóre aplikacje sprawiają, że pliki stają się anonimowe, ponieważunlink()
są otwarte, a uchwyt pliku otwarty, więc może się wyświetlać,ls *
alerm *
nie może go złapać.*
istnieje różnica między tymls
, co by się wyświetlało, a tym, corm
działa, ponieważ lista zawartości katalogu zmieniła się pomiędzy.ls *
w rzeczywistości może pokazać plik, którego już nie ma.ls *
irm *
nie są odpowiedzialni za rozszerzanie globu - robi to powłoka przed przekazaniem jej do polecenia.Oznacza to, że możesz używać dowolnego polecenia z rozszerzoną listą plików - więc użyłbym czegoś, co robi tak mało, jak to możliwe.
Lepszym sposobem na zrobienie tego (a przynajmniej innym sposobem) jest pominięcie środkowego człowieka.
echo *
pokaże ci dokładnie, co zostanie przekazane twojemurm
poleceniu.źródło
printf "%s\n" *
aby uzyskać jednoznaczny widok nazw plików ze spacjami. (Lub%q
zamiast tego radzić sobie również z znakami nowej linii i znakami kontrolnymi, kosztem brzydszych wyników.)Co powiesz na:
Zasadniczo symbole wieloznaczne rozwijające się do rzeczy zaczynających się od
-
(lub ręcznie wprowadzanych rzeczy zaczynających się od,-
ale które wyglądają trochę bardziej jak oszukiwanie) mogą być interpretowane inaczej przezls
irm
.źródło
Tam są przypadki brzegowe gdzie co
ls
pokazuje nie to, corm
usuwa. Raczej skrajny, ale na szczęście łagodny, jeśli przekazany argument jest dowiązaniem symbolicznym do katalogu:ls
pokaże wszystkie pliki w katalogu z dowiązaniem symbolicznym, a jednocześnierm
usunie dowiązanie symboliczne, pozostawiając oryginalny katalog i jego zawartość nietkniętą:źródło
ln -s $HOME some_link; ls some_link
wynikisome_link@
dla mnie, alels
alias dols -F
. Najwyraźniej-F
zmienia zachowanie na wyświetlanie linku zamiast dereferencji. Nie spodziewałem się tego.ls -l
na przykład celuje w link, a nie w miejsce docelowe ... muszą istnieć sposoby na sprawdzenie samego linku.ls
irm
.ls some_link/
,ls -H some_link
czyls -L some_link
to będzie lista połączony do katalogu, nawet jeśli dodać-F
lub-l
. I odwrotnie (w pewnym sensie)-d
mówi , że należy patrzeć na katalog, a nie na jego zawartość; porównajls -l /tmp
ils -ld /tmp
.ls
. Zasadniczo wykazujesz, dlaczego policzenie zachowań z różnymi flagami nie jest warte zawracania sobie głowy tym pytaniem ...Jeśli robisz tylko
ls
zamiastls -a
, takrm
można usunąć ukryte pliki nie widzieli sięls
bez-a
.Przykład:
Według :
ls dir_test
: wyświetli tylko test2ls -A dir_test
: wyświetli test2 + .testrm -r dir_test
: usunie wszystkie (.test + test2)Mam nadzieję, że ci to pomoże.
źródło
rm *
nie usuwa plików kropkowych. Jeśli tak,ls *
pokaże je również.ls *
nie wyświetlaj ukrytych plików.ls -a
pokaże.
,..
,.test
itest2
. Możesz zmienić przykład użycials -A
, który zawiera listę wszystkich elementów oprócz.
i..
(tj. Tylko.test
itest2
).Istnieje już wiele dobrych odpowiedzi, ale chcę dodać głębszy wgląd.
Zadaj sobie pytanie: ile parametrów zostanie przekazanych
ls
, jeśli napiszesz... Zauważ, że
ls
polecenie nie otrzymuje*
parametru jako, jeśli istnieją pliki, które*
można rozwinąć. Zamiast tego powłoka najpierw wykonuje globbing przed wywołaniem polecenia, więcls
polecenie faktycznie otrzymuje tyle parametrów, ile jest plików dopasowanych przez globbing. Aby wyłączyć globowanie, podaj parametr.To jest prawdziwe dla dowolnej komendy:
echo *
vsecho '*'
.Jest skrypt, wywołaj go,
countparams.sh
aby przetestować efekt. Informuje, ile parametrów przekazał, i podaje je.Spraw, by był wykonywalny i działał
./countparams.sh *
. Ucz się z jego wyników!źródło
Glob rozszerzy się w ten sam sposób za każdym razem, jeśli zawartość katalogu będzie taka sama w tych dwóch różnych czasach.
Jeśli naprawdę chcesz sprawdzić, co zostanie usunięte, użyj
rm -i *.txt
. Poprosi Cię osobno o każdy plik przed (próbą) usunięcia.Gwarantuje to bezpieczeństwo przed warunkami wyścigowymi:
ls *.txt
/ tworzony jest nowy plik /rm *.txt
ponieważ monituje o każdy plik ten sam program, który usuwa.
To jest zbyt skomplikowane dla zwykłego użytkowania, a jeśli alias
rm
dorm -i
, znajdziesz się przy użyciu\rm
lubrm -f
dość często. Ale warto przynajmniej wspomnieć, że istnieje rozwiązanie stanu wyścigu. (Jest nawet przenośny na systemy inne niż GNU: POSIXrm(1)
określa-i
opcję ).Inną opcją może być tablica bash:
to_remove=(*.txt)
następnie poproś użytkownika o potwierdzenie (być może po wykonaniuls -ld -- "${to_remove[@]}"
)rm -- "${to_remove[@]}"
. Tak więc ekspansja globu odbywa się tylko raz, a lista jest przekazywana dosłownie dorm
.Inną praktycznie użyteczną opcją jest GNU
rm -I
( strona podręcznika), która monituje o usunięcie więcej niż 4 elementów. (Ale nie pokazuje listy, tylko sumę.) Używamalias rm='rm -I'
na pulpicie.Jest to miłe zabezpieczenie przed powracającym palcami tłuszczu z półtypowym wzorem, który pasuje zbyt wiele. Ale korzystanie z
ls
pierwszego jest ogólnie dobre w katalogu, który posiadasz lub w systemie dla jednego użytkownika, a gdy nie ma procesów w tle, które mogłyby asynchronicznie tworzyć nowe pliki. Aby uchronić się przed palcami tłuszczu, nie piszrm -rf /foo/bar/baz
od lewej do prawej.rm -rf /
jest w specjalnej obudowie, alerm -rf /usr
nie jest! Pomiń-rf
część lub zacznij odls
i dodajrm -rf
część dopiero po wpisaniu ścieżki.źródło