Чому друк знаходить ведучий "./", якщо шляхи не вказані?


13

Чому саме це findвиводить ./результат, якщо шлях не заданий?

$ find
./file1
./file2
./file3

У чому причина цього не надрукована?

$ find
file1
file2
file3

Відповіді:


16

Причина , чому ви бачите це відбувається тому , що розробник GNU вибрав забезпечити «розумне» поведінку для , коли ні один шлях не дається. На відміну від POSIX , не зазначено, що параметр не є обов'язковим:find find

findУтиліта має рекурсивно спускатися по ієрархії каталогів з кожного файлу , вказаного шляхом , оцінюючи логічне вираз , що складається з первинних , описаних в розділі операндів для кожного знайденого файлу. Кожен операнд контуру оцінюється незмінним, як він був наданий, включаючи всі <slash>символи, що відкладаються ; всі імена шляхів для інших файлів, що зустрічаються в ієрархії, повинні складатися з конкатенації поточного операнда контуру, a, <slash>якщо поточний операнд контуру не закінчився одним, та імені файла відносно операнду шляху. Відносна частина не повинна містити компонентів, що містять крапки або крапки, не затримуєтьсясимволи та лише окремі <slash>символи між компонентами імені шляху.

Ви можете бачити різницю в конспекті для кожного. GNU має (як це умовно) додаткові елементи у квадратних дужках:

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

поки POSIX не вказує, що це може бути необов'язково:

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

У програмі GNU це зроблено в ftsfind.c:

  якщо (порожньо)
    {
      / *
       * Ми використовуємо тут тимчасову змінну, оскільки деякі дії змінюються
       * шлях тимчасово. Отже, якщо ми використовуємо струнну константу,
       * ми отримуємо coredump. Найкращий приклад цього - якщо ми скажемо
       * "знайти -printf% H" (зверніть увагу, не "знайти. -printf% H").
       * /
      char defaultpath [2] = ".";
      повернути пошук (шлях за замовчуванням);
    }

а "."для простоти використовується буквальне . Так ви побачите той самий результат і з

find

і

find .

тому що (і POSIX погоджується) даний шлях буде використаний для префіксації результатів (див. вище для конкатенації ).

Трохи працюючи, можна було б визначити, коли функція вперше була додана; він був присутній у початковому створенні "findutils" у 1996 році (див. 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);
+}

З журналу змін 3,8 це було очевидно

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 "."

11

Зазвичай можна виконати післяобробку файлів, і в цьому випадку може бути величезна перевага для запуску імені файлу ./. Зокрема, якщо ім'я файлу починається з -, наступна команда може інтерпретувати це ім'я файлу як варіант. ./уникає цього.

Як приклад, розглянемо каталог з цими файлами:

$ ls
--link  --no-clobber

Тепер уявіть, як ця команда працюватиме, якби імена файлів були надані без ./фронту:

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

Ми можемо проілюструвати проблему findсамим собою. Запустимо його в той же каталог, що і вище. Наступні роботи:

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

Наступні помилки:

$ find *
find: unknown predicate `--link'
Try 'find --help' for more information.

1
Це має сенс. Але тоді виникає питання, чому це не є "." коли ти біжиш find *.
Н.Р.

@nr Добре. Я очікую, що він так поводиться для якоїсь історичної сумісності. Я додав у відповідь приклад того, чому це небажана поведінка.
John1024

3
Деякі версії file вимагають від користувача дати шлях (наприклад, пошук BSD в OS X). Тому зазвичай потрібно прямо сказати щось подібне find . -type f .... Звідси це не є великим кроком для деяких версій знаходження (наприклад, GNU find), щоб просто за замовчуванням .залишити все інше як є.
ilkkachu

1
Причиною find *не відображення цього .є те, що *перераховує всі файли та папки, але виключає .. Зробіть echo *у каталозі, який містить лише один або два файли, і ви побачите, що .це не в списку. Таким чином, find *оперує кожним розширеним файлом. Це те саме, що ви сказали find Desktop/з домашнього каталогу. Ви побачите результат якDesktop/foo_bar.txt
Сергій Колодяжний

1
@ John1024: Я вважаю, що Мрігеш та Томас Дікі правильно відповіли на питання. У цій відповіді зазначено, чому це зручно, як findповодиться так, як це робиться. Чи є у вас якась авторитетна довідкова інформація, яка б підтверджувала загальну заяву, яка findбула покликана поводитись таким чином з цієї причини?
G-Man каже: "Відновіть Моніку"

4

findПотреби команди шляху (и) для пошуку. Якщо ми не вказуємо жодного, він використовує поточний каталог ( .) як вихідний пункт. Аналогічно, якщо ви проходите шлях, наприклад /tmp, він вважає це своїм вихідним пунктом. І тому результати.

Якщо поточний каталог:

        $ find
or
        $ find .

output:
        ./file1
        ./file2
        ./file3

Якщо /tmpкаталог:

        $ find /tmp

output:
        /tmp/file4
        /tmp/file5

Якщо abcкаталог у поточному каталозі:

        $ find abc

output:
        abc/file6
        abc/file7

Якщо в поточному каталозі декілька каталогів:

        $ find fu bar

output:
        fu/file10
        fu/file11
        bar/file8
        bar/file9

Так, я погоджуюсь, findпотрібен шлях для пошуку чого-небудь, і це значення за замовчуванням до поточного каталогу. Питання в тому, чому він виводить провідне, ./коли file.txtце точно так само, як ./file.txt.
Н.Р.

1
його не те, що знаходить додавання "." на початку фактично він додає все, що ви надаєте як шлях, будь то "/ tmp" "abc" або ".". Він поверне всі значення відповідно.
Mrigesh Priyadarshi

-2

Якщо ви не вказали шлях, findкоманда приймає ${PWD}як шлях і роздруковує його на своєму виході. Користувач, не вказавши шлях, не змінює спосіб findроботи. І пошук завжди працює з шляхами за замовчуванням.


1
Я бачу. Але якщо ви виконаєте його під /tmp, тоді $PWDце /tmpне так ./.
Н.Р.

якщо ви хочете переглянути попередньо /tmp, запустіть команду. find /tmpЯкщо ви не вказали шлях, це завжди буде поточна директорія, а саме./
MelBurslan

1
Це не те, що я хочу бачити раніше /tmp. Це те, що не може бути $PWD.
Н.Р.

Мої вибачення ${PWD}були невірною багатослівністю
Мельбурслан

2
Ні, він не передбачає $ PWD. Порівняйте висновок find ., find $PWDі find(без шляху, якщо ваша знахідка підтримує).
ilkkachu
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.