Czy próbujesz usunąć wszystko z bieżącego katalogu? Jaki jest bieżący katalog?
cutrightjm
Możesz użyć setopt extended_glob(lub nawet zwykłego rm * >/dev/null 2>&1), ale naprawdę powinieneś zrobić obejście, którego nie potrzebujesz rm *, to jest zupełnie niebezpieczne
grochmal
Trzeba naprawdę być zatopienie się /dev/nullraczej wtedy dev/zero. Ponadto brakuje przekierowania stderr& ; tak powinno być 2>&1.
roaima
Komunikat o błędzie jest generowany zshpodczas oceny polecenia, a nie w czasie wykonywania samego polecenia (z powodu błędu polecenie nawet się nie uruchamia). Przekierowania danych wyjściowych wpłynęłyby tylko na dane wyjściowe polecenia, a nie na samą powłokę.
Adaephon
Odpowiedzi:
42
To zachowanie jest kontrolowane przez opcję Zshnomatch . Domyślnie, jeśli wiersz polecenia zawiera wyrażenie globbing, które nie pasuje do niczego, Zsh wydrukuje wyświetlony komunikat o błędzie i w ogóle nie uruchomi polecenia. Możesz to wyłączyć, uruchamiając
setopt +o nomatch
Następnie wyrażenia globbing, które nie pasują do niczego, pozostaną bez zmian, a otrzymasz komunikat o błędzie rm( z którego możesz wyłączyć korzystanie -f, chociaż to zły pomysł, ponieważ wymusi usunięcie w innych sytuacjach, w których możesz nie chcieć).
Zachowanie jest również kontrolowane przez opcje nullglobi cshnullglob. Jeśli nullglobjest ustawiony i nie znaleziono pasującego pliku, wzorzec jest usuwany z listy argumentów zamiast generowania błędu. Ustawienie cshnullglobma podobny efekt, chyba że wszystkie wzorce w poleceniu nie pasują, w takim przypadku zostanie zgłoszony błąd. Uwaga: ustawienie nullgloblub cshnullglobzastąpienie nomatch. Można również ustawić nullglobdla pojedynczych wzorów za pomocą kwalifikatora glob N: rm *(N).
Adaephon
nomatchjest mniej niż idealny, to właśnie robią muszle Bourne'a. Jeśli wzorzec nie pasuje, jest przekazywany „tak jak jest” rm(!), Co rmspowoduje błąd, lub gorzej może usunąć niewłaściwy plik dla wzorca, *.[ch]na przykład!
Stéphane Chazelas
9
Co chciałbyś zamiast tego zrobić? rmW ogóle nie działa (1)? Czy uruchomić go z dosłownym *argumentem, jak w innych powłokach podobnych do Bourne'a (2)? Uruchomić bez żadnych argumentów (3)?
files=(*(N)); (($#files)) && rm -- $files. Albo (rm -- *) 2> /dev/nullale również ukryć rzeczywiste błędy przez rmco byłoby głupie. Możesz odrzucić zshbłąd, ale przywróć stderr dla rmpolecenia za pomocą(rm -- * 2>&3 3>&-) 3>&2 2> /dev/null
emulate sh -c 'rm -- *' 2> /dev/null. Potem jak w shktóry zshteraz emulowane dla tej linii pojedynczej poleceń, bez dopasowywania *jest przekazywana jako-jest rmi rmskarży się, jako że *plik nie istnieje. Mamy tłumić rm„s stderr jak można zrobić w shcelu powstrzymania, że komunikat o błędzie, ale znowu, że to głupie, jak to ukryć prawdziwych błędów, rmw przeciwieństwie do błędu poniesionych przez pobycie shprzechodząc dosłownym *się rm. rm -f '*'nie narzekałby jednak na nieistniejący *plik, więc możesz to zrobićemulate sh -c 'rm -f -- *'
rm -- *(N). rmbyłoby narzekać chociaż gdy nie przeszedł żadnego argumentu, choć znowu nie rm -f: rm -f -- *(N).
Ogólnie rzecz biorąc, rm -fto polecenie, którego chcesz użyć, jeśli chcesz, aby wszystkie pliki zniknęły i pojawia się błąd tylko wtedy, gdy plików nie można usunąć lub IOW nadal tam są po rmpowrocie. Zasadniczo chcesz również używać -fskryptów, aby uniknąć monitowania użytkownika w niektórych sytuacjach.
Tutaj dzwonienie, rmgdy glob nie pasuje, jest błędne. Zachowanie sh1 jest nieprawidłowe. Jest to nieszkodliwe dla takiego wzoru *, ale dla takiego jak *.[ch], przekazanie takiego *.[ch]jak jest, gdy nie pasuje, może spowodować *.[ch]pomyłkowe usunięcie pliku:
$ ls
*.[ch] foo.txt
$ zsh -c 'rm *.[ch]'
zsh:1: no matches found:*.[ch]
$ ls
*.[ch] foo.txt
$ sh -c 'rm *.[ch]'
$ ls
foo.txt
Niepowodzeniem z błędem jest najbardziej sensowne rzeczy do zrobienia i to, co zsh(i fish, csh, tcsh, bash -o failglobi oryginalny Unix shell) robi.
A jeśli chcesz sam zająć się tym specjalnym przypadkiem, zshułatwia to jego (N)kwalifikator globalny (dla noglob ), jak w przypadku (1) powyżej. fish(przynajmniej w najnowszej wersji ) czyni to jeszcze łatwiejszym, ponieważ wykonuje ukryte polecenie dla setpolecenia. Odpowiednikiem byłoby:
set files *if count $files >/dev/null
rm -f -- $files
end
1 . Ściśle mówiąc, to dopiero shod czasu powłoki Bourne'a (od Unixa V7 w 1979 r.); wcześniejsze wersje sh(które /etc/globwzywały nieoznaczone symbole wieloznaczne, z których pochodzi nazwa globu ) zachowywały się jak cshlub zsh -o cshnullglob, to znaczy /etc/globprzerywałyby polecenie, jeśli żadna z globów nie pasowała (i tłumiłyby niepasujące globy, jeśli przynajmniej jeden z nich miał jakieś dopasowanie). Zachowanie zostało złamane przez powłokę Bourne'a.
Myślę, że spodziewa się otrzymać komunikat o błędzie z rmpowłoki, a nie z powłoki. Coś w stylu „rm: nie można usunąć` * ': Nie ma takiego pliku ani katalogu ”.
Emmanuel
@Emmanuel, to jest 2: emulate sh -c 'rm -- *'uzyskać (błędne IMO) zachowanie powłoki Bourne'a.
Stéphane Chazelas
@Stephane_Chazelas, jak jest napisane, 2 jest właściwą odpowiedzią na pytanie, którego nie zadał :).
Emmanuel
@Emmanuel, wszystkie 3 odpowiedzi na pytanie: jak pozbyć się błędu „Brak dopasowania”. Kod OP pomija rmbłędy. Jest to coś, co można zrobić w innych powłokach, aby ukryć błąd, gdy nie ma pasującego pliku, a to powoduje również tłumienie oryginalnych błędów rm. Moja odpowiedź podkreśla, że i mam nadzieję, że preferowane jest zachowanie Zsh.
setopt extended_glob
(lub nawet zwykłegorm * >/dev/null 2>&1
), ale naprawdę powinieneś zrobić obejście, którego nie potrzebujeszrm *
, to jest zupełnie niebezpieczne/dev/null
raczej wtedydev/zero
. Ponadto brakuje przekierowania stderr&
; tak powinno być2>&1
.zsh
podczas oceny polecenia, a nie w czasie wykonywania samego polecenia (z powodu błędu polecenie nawet się nie uruchamia). Przekierowania danych wyjściowych wpłynęłyby tylko na dane wyjściowe polecenia, a nie na samą powłokę.Odpowiedzi:
To zachowanie jest kontrolowane przez opcję Zsh
nomatch
. Domyślnie, jeśli wiersz polecenia zawiera wyrażenie globbing, które nie pasuje do niczego, Zsh wydrukuje wyświetlony komunikat o błędzie i w ogóle nie uruchomi polecenia. Możesz to wyłączyć, uruchamiającNastępnie wyrażenia globbing, które nie pasują do niczego, pozostaną bez zmian, a otrzymasz komunikat o błędzie
rm
( z którego możesz wyłączyć korzystanie-f
, chociaż to zły pomysł, ponieważ wymusi usunięcie w innych sytuacjach, w których możesz nie chcieć).źródło
nullglob
icshnullglob
. Jeślinullglob
jest ustawiony i nie znaleziono pasującego pliku, wzorzec jest usuwany z listy argumentów zamiast generowania błędu. Ustawieniecshnullglob
ma podobny efekt, chyba że wszystkie wzorce w poleceniu nie pasują, w takim przypadku zostanie zgłoszony błąd. Uwaga: ustawienienullglob
lubcshnullglob
zastąpienienomatch
. Można również ustawićnullglob
dla pojedynczych wzorów za pomocą kwalifikatora globN
:rm *(N)
.nomatch
jest mniej niż idealny, to właśnie robią muszle Bourne'a. Jeśli wzorzec nie pasuje, jest przekazywany „tak jak jest”rm
(!), Corm
spowoduje błąd, lub gorzej może usunąć niewłaściwy plik dla wzorca,*.[ch]
na przykład!Co chciałbyś zamiast tego zrobić?
rm
W ogóle nie działa (1)? Czy uruchomić go z dosłownym*
argumentem, jak w innych powłokach podobnych do Bourne'a (2)? Uruchomić bez żadnych argumentów (3)?files=(*(N)); (($#files)) && rm -- $files
. Albo(rm -- *) 2> /dev/null
ale również ukryć rzeczywiste błędy przezrm
co byłoby głupie. Możesz odrzucićzsh
błąd, ale przywróć stderr dlarm
polecenia za pomocą(rm -- * 2>&3 3>&-) 3>&2 2> /dev/null
emulate sh -c 'rm -- *' 2> /dev/null
. Potem jak wsh
któryzsh
teraz emulowane dla tej linii pojedynczej poleceń, bez dopasowywania*
jest przekazywana jako-jestrm
irm
skarży się, jako że*
plik nie istnieje. Mamy tłumićrm
„s stderr jak można zrobić wsh
celu powstrzymania, że komunikat o błędzie, ale znowu, że to głupie, jak to ukryć prawdziwych błędów,rm
w przeciwieństwie do błędu poniesionych przez pobyciesh
przechodząc dosłownym*
sięrm
.rm -f '*'
nie narzekałby jednak na nieistniejący*
plik, więc możesz to zrobićemulate sh -c 'rm -f -- *'
rm -- *(N)
.rm
byłoby narzekać chociaż gdy nie przeszedł żadnego argumentu, choć znowu nierm -f
:rm -f -- *(N)
.Ogólnie rzecz biorąc,
rm -f
to polecenie, którego chcesz użyć, jeśli chcesz, aby wszystkie pliki zniknęły i pojawia się błąd tylko wtedy, gdy plików nie można usunąć lub IOW nadal tam są porm
powrocie. Zasadniczo chcesz również używać-f
skryptów, aby uniknąć monitowania użytkownika w niektórych sytuacjach.Tutaj dzwonienie,
rm
gdy glob nie pasuje, jest błędne. Zachowaniesh
1 jest nieprawidłowe. Jest to nieszkodliwe dla takiego wzoru*
, ale dla takiego jak*.[ch]
, przekazanie takiego*.[ch]
jak jest, gdy nie pasuje, może spowodować*.[ch]
pomyłkowe usunięcie pliku:Niepowodzeniem z błędem jest najbardziej sensowne rzeczy do zrobienia i to, co
zsh
(ifish
,csh
,tcsh
,bash -o failglob
i oryginalny Unix shell) robi.A jeśli chcesz sam zająć się tym specjalnym przypadkiem,
zsh
ułatwia to jego(N)
kwalifikator globalny (dla noglob ), jak w przypadku (1) powyżej.fish
(przynajmniej w najnowszej wersji ) czyni to jeszcze łatwiejszym, ponieważ wykonuje ukryte polecenie dlaset
polecenia. Odpowiednikiem byłoby:Zobacz Dlaczego nullglob nie jest domyślny, aby uzyskać więcej informacji.
1 . Ściśle mówiąc, to dopiero
sh
od czasu powłoki Bourne'a (od Unixa V7 w 1979 r.); wcześniejsze wersjesh
(które/etc/glob
wzywały nieoznaczone symbole wieloznaczne, z których pochodzi nazwa globu ) zachowywały się jakcsh
lubzsh -o cshnullglob
, to znaczy/etc/glob
przerywałyby polecenie, jeśli żadna z globów nie pasowała (i tłumiłyby niepasujące globy, jeśli przynajmniej jeden z nich miał jakieś dopasowanie). Zachowanie zostało złamane przez powłokę Bourne'a.źródło
rm
powłoki, a nie z powłoki. Coś w stylu „rm: nie można usunąć` * ': Nie ma takiego pliku ani katalogu ”.emulate sh -c 'rm -- *'
uzyskać (błędne IMO) zachowanie powłoki Bourne'a.rm
błędy. Jest to coś, co można zrobić w innych powłokach, aby ukryć błąd, gdy nie ma pasującego pliku, a to powoduje również tłumienie oryginalnych błędów rm. Moja odpowiedź podkreśla, że i mam nadzieję, że preferowane jest zachowanie Zsh.