Dlaczego find drukuje wiodące „./”, jeśli nie podano żadnych ścieżek?

13

Dlaczego finddrukuje prowadzące ./do wyników, jeśli nie podano ścieżek?

$ find
./file1
./file2
./file3

Jaki jest powód, aby tego nie drukować?

$ find
file1
file2
file3
nr
źródło

Odpowiedzi:

16

Powód dlaczego widzisz to dlatego, że deweloper GNU wybrał , aby zapewnić „rozsądne” zachowanie dla gdy żaden nie został podany. Natomiast POSIX nie stwierdza, że ​​parametr jest opcjonalny:find find

findNarzędzie musi rekurencyjnie schodzą hierarchii katalogów z każdego pliku określonego przez ścieżkę , oceny logicznego, złożoną z barw podstawowych opisanych w sekcji operandów dla każdego pliku spotykanych. Każdy argument ścieżki jest oceniany w niezmienionej postaci, w tym w jakiej został dostarczony, w tym wszystkie <slash>znaki końcowe ; wszystkie nazwy ścieżek dla innych plików napotkanych w hierarchii składają się z konkatenacji bieżącego argumentu ścieżki, a <slash>jeśli bieżący argument ścieżki nie kończy się na jednym, i nazwy pliku względem argumentu ścieżki. Część względna nie powinna zawierać żadnych kropek ani elementów kropka-kropka, brak spływuznaki i tylko pojedyncze <slash>znaki między komponentami ścieżki.

Możesz zobaczyć różnicę w streszczeniu każdego z nich. GNU ma (zgodnie z konwencją) elementy opcjonalne w nawiasach kwadratowych:

find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...]
       [expression]

podczas gdy POSIX nie wskazuje, że może być opcjonalny:

find [-H|-L] path... [operand_expression...]

W programie GNU odbywa się to w ftsfind.c:

  jeśli (pusty)
    {
      / *
       * Używamy tutaj zmiennej tymczasowej, ponieważ niektóre akcje się zmieniają
       * ścieżka tymczasowo. Dlatego jeśli użyjemy stałej ciągu,
       * otrzymujemy rdzeń rdzeniowy. Najlepszym tego przykładem jest powiedzmy
       * „find -printf% H” (uwaga, a nie „find. -printf% H”).
       * /
      char defaultpath [2] = ".";
      return find (defaultpath);
    }

i "."dla uproszczenia stosuje się literał . Dzięki temu zobaczysz ten sam wynik

find

i

find .

ponieważ (i POSIX się zgadza) podana ścieżka zostanie użyta do prefiksu wyników (patrz powyżej konkatenacja ).

Przy odrobinie pracy można było ustalić, kiedy funkcja została dodana po raz pierwszy; był obecny przy tworzeniu „findutils” w 1996 r. (patrz find.c):

+  /* If no paths are given, default to ".".  */
+  for (i = 1; i < argc && strchr ("-!(),", argv[i][0]) == NULL; i++)
+    process_top_path (argv[i]);
+  if (i == 1)
+    process_top_path (".");
+
+  exit (exit_status);
+}

Z dziennika zmian dla znalezienia 3.8 było to najwyraźniej

Sat Dec 15 19:01:12 1990  David J. MacKenzie  (djm at egypt)

        * find.c (main), util.c (usage): Make directory args optional,
        defaulting to "."
Thomas Dickey
źródło
11

Zwykle wykonuje się przetwarzanie końcowe plików, a w takim przypadku rozpoczęcie nazwy pliku może być ogromną zaletą ./. W szczególności, jeśli nazwa pliku zaczyna się od -, kolejne polecenie może zinterpretować tę nazwę pliku jako opcję. ./unika tego.

Jako przykład rozważmy katalog z tymi plikami:

$ ls
--link  --no-clobber

Teraz wyobraź sobie, jak to polecenie zadziałałoby, gdyby nazwy plików zostały podane bez znaku z ./przodu:

$ find -type f -exec cp -t ../ {} +

Możemy zilustrować problem findsam w sobie. Uruchommy go w tym samym katalogu, co powyżej. Następujące prace:

$ find ./*
./--link
./--no-clobber

Następujące niepowodzenie:

$ find *
find: unknown predicate `--link'
Try 'find --help' for more information.
John1024
źródło
1
To ma sens. Ale pojawia się pytanie, dlaczego nie wypisuje „.” kiedy biegniesz find *.
nr
@nr Dobra uwaga. Oczekuję, że tak się zachowuje dla pewnego rodzaju zgodności historycznej. Do odpowiedzi dodałem przykład, dlaczego jest to niepożądane zachowanie.
John1024,
3
Niektóre wersje file wymagają od użytkownika podania ścieżki (np. BSD znajdź w OS X). Więc zwykle musisz wyraźnie powiedzieć coś takiego find . -type f .... Stąd nie jest wielkim krokiem dla niektórych wersji find (jak GNU find), aby po prostu domyślnie .pozostawił wszystko inne bez zmian .
ilkkachu
1
Powodem, dla którego find *nie pokazano, .jest to, że *wyświetla listę wszystkich plików i folderów, ale wyklucza .. Zrób to echo *w katalogu, który zawiera tylko jeden lub dwa pliki, a zobaczysz, że .nie ma go na liście. Dlatego find *działa na każdym rozwiniętym pliku. To tak, jakbyś powiedział find Desktop/z katalogu domowego. Zobaczysz wynik jakoDesktop/foo_bar.txt
Sergiy Kolodyazhnyy
1
@ John1024: Uważam, że Mrigesh i Thomas Dickey poprawnie odpowiedzieli na pytanie. Ta odpowiedź wyjaśnia, dlaczego jest tak wygodne, jak się findzachowuje. Czy masz jakieś wiarygodne informacje referencyjne na poparcie dorozumianego twierdzenia, które z tego powodufind zostało zaprojektowane w taki sposób ?
G-Man mówi „Przywróć Monikę”
4

findŚcieżka potrzeby dowodzenia (s), aby wyszukanie. Jeśli nie podamy żadnych, użyje bieżącego katalogu ( .) jako punktu początkowego. Podobnie, jeśli miniesz ścieżkę, np /tmp. Uważa to za swój punkt początkowy. A zatem wyniki.

Jeśli bieżący katalog:

        $ find
or
        $ find .

output:
        ./file1
        ./file2
        ./file3

Jeśli /tmpkatalog:

        $ find /tmp

output:
        /tmp/file4
        /tmp/file5

Jeśli abckatalog w bieżącym katalogu:

        $ find abc

output:
        abc/file6
        abc/file7

Jeśli wiele katalogów w bieżącym katalogu:

        $ find fu bar

output:
        fu/file10
        fu/file11
        bar/file8
        bar/file9
Mrigesh Priyadarshi
źródło
Tak, zgadzam się, że findpotrzebuję ścieżki do wyszukiwania czegokolwiek i że domyślnie jest to bieżący katalog. Pytanie brzmi, dlaczego wypisuje on wiodące, ./gdy file.txtjest taki sam jak ./file.txt.
nr
1
to nie to, że find dodaje „.” na początku dodaje to, co podajesz jako ścieżkę, niezależnie od tego, czy jest to „/ tmp”, „abc” czy „.”. Zwróci odpowiednio wszystkie wartości.
Mrigesh Priyadarshi,
-2

Jeśli nie podasz ścieżki, findpolecenie przyjmuje ${PWD}ścieżkę i wypisuje ją na wyjściu. Użytkownik nieokreślający ścieżki nie zmienia sposobu finddziałania. I find zawsze domyślnie działa ze ścieżkami.

MelBurslan
źródło
1
Widzę. Ale jeśli wykonasz to pod /tmp, $PWDto /tmpnie jest ./.
nr
jeśli chcesz zobaczyć poprzedni /tmp, uruchom polecenie find /tmpJeśli nie podasz ścieżki, zawsze będzie to katalog bieżący, czyli./
MelBurslan,
1
Nie chodzi o to, że chcę widzieć, jak się poprzedza /tmp. Po prostu nie może być $PWD.
nr
Przepraszam ${PWD}za niepoprawne tłumaczenie
MelBurslan
2
Nie, nie zakłada $ PWD. Porównaj wyjście find ., find $PWDi find(bez ścieżki, jeśli znalezisko to obsługuje).
ilkkachu