znajdź seach wewnątrz podanej ścieżki, tak jak jest powiedziane. Więc jeśli wpiszesz, ./że nie pasujefoo
Costas
@Costas: Rozumiem to. Nie rozumiem tylko, dlaczego zrobiło to różnicę, jeśli podałem absolutną ścieżkę find.
York,
@York W niektórych sytuacjach nie ma właściwego zachowania. Wyobraź sobie dowiązanie symboliczne o nazwie barwskazującej plik, fooktóry znajduje się poza ścieżką wyszukiwania. Czy to będzie pasować czy nie?
Hauke Laging
1
.I /tmp/foonie są takie same - są to dwa różne twarde linki do tego samego katalogu; find /tmp/foo/. -name 'foo'też niczego nie znajduje.
jimmij
@jimmij: kiedy uruchomiłem find /tmp/foo -name 'foo', prosiłem bash o znalezienie w katalogu /tmp/foopliku o nazwie „foo”. Ponieważ katalog /tmp/foojest pusty, nie powinien nic zwracać. Nie rozumiem, dlaczego powraca /tmp/foo. Z drugiej strony, kiedy uruchomiłem find . -name 'foo', prosiłem bash o to samo, tj. Znalezienie pliku w bieżącym katalogu (który tak się kiedyś stało /tmp/foo), którego nazwa to „foo”, i nie zwraca niczego, co ma sens.
York,
Odpowiedzi:
15
findprzegląda określone drzewa katalogów i ocenia podane wyrażenie dla każdego znalezionego pliku. Podróż rozpoczyna się na podanej ścieżce. Oto podsumowanie tego, jak find . -name foodziała:
Pierwsza ścieżka w wierszu poleceń: .
Czy nazwa podstawowa ( .) pasuje do wzorca foo? Nie, więc nic nie rób.
Tak się składa, że /tmp/foojest to inna nazwa tego samego katalogu. Ale findnie wie o tym (i nie powinien próbować się tego dowiedzieć).
Czy ścieżka jest katalogiem? Tak, więc przejdź to. Wymień wpisy .i dla każdego wpisu wykonaj proces przejścia.
Katalog jest pusty: nie zawiera żadnych pozycji innych niż .i .., które findnie przechodzą rekurencyjnie. Więc praca jest skończona.
I find /tmp/foo:
Pierwsza ścieżka w wierszu poleceń: /tmp/foo
Czy nazwa podstawowa ( foo) pasuje do wzorca foo? Tak, więc warunek jest zgodny.
Brak warunku związanego z tym warunkiem, dlatego wykonaj domyślną akcję, która polega na wydrukowaniu ścieżki.
Czy ścieżka jest katalogiem? Tak, więc przejdź to. Wymień wpisy /tmp/fooi dla każdego wpisu wykonaj proces przejścia.
Katalog jest pusty: nie zawiera żadnych pozycji innych niż .i .., które findnie przechodzą rekurencyjnie. Więc praca jest skończona.
Zdarza się, że .i /tmp/foosą tym samym katalogu, ale to nie wystarczy, aby zagwarantować, że findma ten sam problem na obu. findKomenda ma sposobów na odróżnienie ścieżek do tego samego pliku; -nameorzecznikiem jest jednym z nich. find /tmp/foo -name foodopasowuje katalog początkowy, a także dowolny plik pod nim, który jest wywoływany foo. find . -name .pasuje tylko do katalogu początkowego ( .nigdy nie można go znaleźć podczas przechodzenia rekurencyjnego).
„nie zawiera żadnego wpisu oprócz… i…, które nie przechodzą rekurencyjnie”. Zakładam, że „nie przechodzi rekurencyjnie” odnosi się do „..”. Jeśli jest to poprawne, co znaczy „rekurencyjnie poprzecznie” w kontekście „..”?
Faheem Mitha
@ FaheemMitha „nie przechodzi rekurencyjnie” dotyczy zarówno .i ... (Jeśli findruch .rekurencyjnie, to skończyć się poprzez katalogu znowu i znowu i znowu i ...) .i ..to nie tylko specjalne oznaczenia, pojawiają się jako wpisy do katalogów.
Gilles „SO- przestań być zły”
5
Nie ma normalizacji argumentów wiersza poleceń przed zastosowaniem testów. Zatem wyniki różnią się w zależności od użytej ścieżki (jeśli zaangażowane są dowiązania symboliczne):
cd /tmp
mkdir foo
ln -s foo bar
find /tmp/foo -name foo
find /tmp/bar -name foo
W „twoim przypadku” oba połączenia dawałyby ten sam wynik, co może (bardziej) być mylące. Możesz użyć, -mindepth 1jeśli chcesz ignorować punkty początkowe (może to być inny niż POSIX).
-mindepth 1Pracuje. Jednak nadal nie rozumiem, dlaczego find . -name 'foo'i find /tmp/foo -name 'foo'zachowuję się inaczej.
York,
2
(gnu) find pokazuje wszystkie dopasowania znalezione w ścieżce podanej dla polecenia, ponieważ zaczyna ono porównywanie z argumentami wiersza poleceń, stamtąd zstępuje głębiej w strukturę katalogów (w ten sposób -maxdepth 0ogranicza testy tylko do poziomu podstawowego lub argumentów wiersza poleceń, podczas gdy -mindepth 1pomija argumenty wiersza poleceń, jak man findwyjaśniono). To jest powód, dla którego find /tmp/foo -name 'foo'da jedno dopasowanie, nawet jeśli sam katalog jest pusty.
find . -name 'foo'z drugiej strony nie przyniesie żadnego rezultatu, ponieważ .(kropka) jest specjalnym plikiem, który działa jak hardlink do tego samego i-węzła, co /tmp/foo- jest jak osobna (choć specjalna) nazwa pliku, a nie dowiązanie symboliczne lub wyrażenie, które podlega rozwijanie nazw ścieżek przez powłokę. Dlatego pierwszy test zastosowany przez find w argumentach wiersza poleceń w podanym przykładzie nie pokaże żadnych dopasowań, ponieważ .faktycznie nie pasuje do wzorca nazwy zdefiniowanego w -name 'foo'. Nie robi to również, /tmp/foo/.ponieważ test -namewzorca jest wykonywany tylko na nazwie basename ścieżki (patrz man find), co tutaj znowu jest ..
Chociaż tego zachowania nie można oczekiwać ani wydawać się intuicyjne z punktu widzenia użytkownika (i tak, na początku też mnie zdezorientowałem), nie stanowi ono błędu, ale odpowiada logice i funkcjonalności opisanej na stronach man i stronach informacyjnych dla ( gnu) znajdź.
Próbowałem skomentować odpowiedź Gillesa, ale było to zbyt długo, aby zmieścić się w komentarzu. Z tego powodu stawiam to jako odpowiedź na moje własne pytanie.
Wyjaśnienie Gillesa (a także Sheveka) jest jasne i ma sens. Kluczową kwestią jest to, że nie tylko findpróbuje dopasować nazwy plików dla danych ścieżek (rekurencyjnie), ale także próbuje dopasować nazwę podstawową samych ścieżek.
Z drugiej strony, czy jest jakiś dowód na to, że w ten sposób findma działać, a nie błąd? Moim zdaniem byłoby lepiej, gdyby nie powodowało to niespójności wyników, find .a find ABSOLUTE-PATHponieważ niekonsekwencja jest zawsze myląca i mogłaby zmarnować programistom wiele czasu na próbę ustalenia „co było nie tak”. W moim przypadku pisałem skrypt, a ścieżka została zaczerpnięta ze zmiennej. Aby mój skrypt działał poprawnie, myślę o tym, aby napisać find $path/. -name 'pattern'.
Wreszcie, myślę, że uzyskanie spójnych wyników findmożna osiągnąć zawsze zastępując .katalog bieżący przed kontynuowaniem.
W fookatalogu, w którym rozpocząłeś wyszukiwanie względne, nie ma żadnego obiektu .
Masz rację, zakładając, że gfindjest on błędny, gdy zgłasza się, /tmp/foogdy używasz nazwy bezwzględnej jako katalogu startowego.
Gfindma różne odchylenia od normy, wygląda na to, że znalazłeś inny. Jeśli podoba Ci się bardziej standardowe rozwiązanie zgodne z normą, polecam, sfindże jest to część schilytools.
-namedotyczy wyników wyszukiwania w katalogu. Żaden z dwóch wspomnianych przypadków nie zwróci pozycji katalogu fooz readdir()operacji.
Podejrzewam, że to też błąd. Oto wynik find --version: find (GNU findutils) 4.4.2 Copyright (C) 2007 Free Software Foundation, Inc. Licencja GPLv3 +: GNU GPL wersja 3 lub nowsza < gnu.org/licenses/gpl.html >
York
Cóż, sprawdziłem twoje przykładowe polecenia za pomocą find(certyfikat POSIX) gfindi sfind; problem istnieje tylko podczas używania gfind. W systemie Linux gfindnie jest instalowany pod własną nazwą, ale pod nazwą find.
schily,
3
Poprawne jest na find /tmp/foo -name foowyjście /tmp/foo. (Cc @York) Jest to zachowanie OpenBSD find, GNU find, BusyBox find, Solaris findi wszelkich innych zgodnych z POSIX find(„Podstawowa powinna ocenić jako prawda, jeśli nazwa basenowa badanej nazwy pliku pasuje do wzorca (…)” - gdy nazwa pliku to taki, który jest przekazywany jako operand ścieżki, nie readdirjest wymagane żadne połączenie).
./
że nie pasujefoo
find
.bar
wskazującej plik,foo
który znajduje się poza ścieżką wyszukiwania. Czy to będzie pasować czy nie?.
I/tmp/foo
nie są takie same - są to dwa różne twarde linki do tego samego katalogu;find /tmp/foo/. -name 'foo'
też niczego nie znajduje.find /tmp/foo -name 'foo'
, prosiłem bash o znalezienie w katalogu/tmp/foo
pliku o nazwie „foo”. Ponieważ katalog/tmp/foo
jest pusty, nie powinien nic zwracać. Nie rozumiem, dlaczego powraca/tmp/foo
. Z drugiej strony, kiedy uruchomiłemfind . -name 'foo'
, prosiłem bash o to samo, tj. Znalezienie pliku w bieżącym katalogu (który tak się kiedyś stało/tmp/foo
), którego nazwa to „foo”, i nie zwraca niczego, co ma sens.Odpowiedzi:
find
przegląda określone drzewa katalogów i ocenia podane wyrażenie dla każdego znalezionego pliku. Podróż rozpoczyna się na podanej ścieżce. Oto podsumowanie tego, jakfind . -name foo
działa:.
.
) pasuje do wzorcafoo
? Nie, więc nic nie rób.Tak się składa, że
/tmp/foo
jest to inna nazwa tego samego katalogu. Alefind
nie wie o tym (i nie powinien próbować się tego dowiedzieć)..
i dla każdego wpisu wykonaj proces przejścia..
i..
, którefind
nie przechodzą rekurencyjnie. Więc praca jest skończona.I
find /tmp/foo
:/tmp/foo
foo
) pasuje do wzorcafoo
? Tak, więc warunek jest zgodny./tmp/foo
i dla każdego wpisu wykonaj proces przejścia..
i..
, którefind
nie przechodzą rekurencyjnie. Więc praca jest skończona.Zdarza się, że
.
i/tmp/foo
są tym samym katalogu, ale to nie wystarczy, aby zagwarantować, żefind
ma ten sam problem na obu.find
Komenda ma sposobów na odróżnienie ścieżek do tego samego pliku;-name
orzecznikiem jest jednym z nich.find /tmp/foo -name foo
dopasowuje katalog początkowy, a także dowolny plik pod nim, który jest wywoływanyfoo
.find . -name .
pasuje tylko do katalogu początkowego (.
nigdy nie można go znaleźć podczas przechodzenia rekurencyjnego).źródło
.
i..
. (Jeślifind
ruch.
rekurencyjnie, to skończyć się poprzez katalogu znowu i znowu i znowu i ...).
i..
to nie tylko specjalne oznaczenia, pojawiają się jako wpisy do katalogów.Nie ma normalizacji argumentów wiersza poleceń przed zastosowaniem testów. Zatem wyniki różnią się w zależności od użytej ścieżki (jeśli zaangażowane są dowiązania symboliczne):
W „twoim przypadku” oba połączenia dawałyby ten sam wynik, co może (bardziej) być mylące. Możesz użyć,
-mindepth 1
jeśli chcesz ignorować punkty początkowe (może to być inny niż POSIX).źródło
-mindepth 1
Pracuje. Jednak nadal nie rozumiem, dlaczegofind . -name 'foo'
ifind /tmp/foo -name 'foo'
zachowuję się inaczej.(gnu) find pokazuje wszystkie dopasowania znalezione w ścieżce podanej dla polecenia, ponieważ zaczyna ono porównywanie z argumentami wiersza poleceń, stamtąd zstępuje głębiej w strukturę katalogów (w ten sposób
-maxdepth 0
ogranicza testy tylko do poziomu podstawowego lub argumentów wiersza poleceń, podczas gdy-mindepth 1
pomija argumenty wiersza poleceń, jakman find
wyjaśniono). To jest powód, dla któregofind /tmp/foo -name 'foo'
da jedno dopasowanie, nawet jeśli sam katalog jest pusty.find . -name 'foo'
z drugiej strony nie przyniesie żadnego rezultatu, ponieważ.
(kropka) jest specjalnym plikiem, który działa jak hardlink do tego samego i-węzła, co/tmp/foo
- jest jak osobna (choć specjalna) nazwa pliku, a nie dowiązanie symboliczne lub wyrażenie, które podlega rozwijanie nazw ścieżek przez powłokę. Dlatego pierwszy test zastosowany przez find w argumentach wiersza poleceń w podanym przykładzie nie pokaże żadnych dopasowań, ponieważ.
faktycznie nie pasuje do wzorca nazwy zdefiniowanego w-name 'foo'
. Nie robi to również,/tmp/foo/.
ponieważ test-name
wzorca jest wykonywany tylko na nazwie basename ścieżki (patrzman find
), co tutaj znowu jest.
.Chociaż tego zachowania nie można oczekiwać ani wydawać się intuicyjne z punktu widzenia użytkownika (i tak, na początku też mnie zdezorientowałem), nie stanowi ono błędu, ale odpowiada logice i funkcjonalności opisanej na stronach man i stronach informacyjnych dla ( gnu) znajdź.
źródło
Próbowałem skomentować odpowiedź Gillesa, ale było to zbyt długo, aby zmieścić się w komentarzu. Z tego powodu stawiam to jako odpowiedź na moje własne pytanie.
Wyjaśnienie Gillesa (a także Sheveka) jest jasne i ma sens. Kluczową kwestią jest to, że nie tylko
find
próbuje dopasować nazwy plików dla danych ścieżek (rekurencyjnie), ale także próbuje dopasować nazwę podstawową samych ścieżek.Z drugiej strony, czy jest jakiś dowód na to, że w ten sposób
find
ma działać, a nie błąd? Moim zdaniem byłoby lepiej, gdyby nie powodowało to niespójności wyników,find .
afind ABSOLUTE-PATH
ponieważ niekonsekwencja jest zawsze myląca i mogłaby zmarnować programistom wiele czasu na próbę ustalenia „co było nie tak”. W moim przypadku pisałem skrypt, a ścieżka została zaczerpnięta ze zmiennej. Aby mój skrypt działał poprawnie, myślę o tym, aby napisaćfind $path/. -name 'pattern'
.Wreszcie, myślę, że uzyskanie spójnych wyników
find
można osiągnąć zawsze zastępując.
katalog bieżący przed kontynuowaniem.źródło
W
foo
katalogu, w którym rozpocząłeś wyszukiwanie względne, nie ma żadnego obiektu .Masz rację, zakładając, że
gfind
jest on błędny, gdy zgłasza się,/tmp/foo
gdy używasz nazwy bezwzględnej jako katalogu startowego.Gfind
ma różne odchylenia od normy, wygląda na to, że znalazłeś inny. Jeśli podoba Ci się bardziej standardowe rozwiązanie zgodne z normą, polecam,sfind
że jest to częśćschilytools
.-name
dotyczy wyników wyszukiwania w katalogu. Żaden z dwóch wspomnianych przypadków nie zwróci pozycji katalogufoo
zreaddir()
operacji.źródło
find --version
: find (GNU findutils) 4.4.2 Copyright (C) 2007 Free Software Foundation, Inc. Licencja GPLv3 +: GNU GPL wersja 3 lub nowsza < gnu.org/licenses/gpl.html >find
(certyfikat POSIX)gfind
isfind
; problem istnieje tylko podczas używaniagfind
. W systemie Linuxgfind
nie jest instalowany pod własną nazwą, ale pod nazwąfind
.find /tmp/foo -name foo
wyjście/tmp/foo
. (Cc @York) Jest to zachowanie OpenBSDfind
, GNUfind
, BusyBoxfind
, Solarisfind
i wszelkich innych zgodnych z POSIXfind
(„Podstawowa powinna ocenić jako prawda, jeśli nazwa basenowa badanej nazwy pliku pasuje do wzorca (…)” - gdy nazwa pliku to taki, który jest przekazywany jako operand ścieżki, niereaddir
jest wymagane żadne połączenie).