Ознайомлення з варіантом знаходження (1) s -exec (фігурні дужки та знак плюс)


17

Використовуючи наступну команду, чи не могли б хто-небудь пояснити, яка саме мета для закінчення фігурних дужок ({}) та знаку плюс (+)?

І як би команда діяла по-іншому, якби вони були виключені з команди?

find . -type d -exec chmod 775 {} +

Відповіді:


19

Фігурні дужки будуть замінені результатами findкоманди, і chmodзапуск буде виконуватися на кожному з них. В +марці findнамагається працювати як кілька команд , як це можливо (так, chmod 775 file1 file2 file3на відміну від chmod 755 file1, chmod 755 file2, chmod 755 file3). Без них команда просто видає помилку. Це все пояснено у man find:

-exec command ;

      Виконати команду ; вірно, якщо статус 0 повернуто. Усі наступні аргументи findповинні бути аргументами команди, поки аргумент, що складається з ' ;'. Рядок ' {}' замінюється поточним ім'ям файлу, який обробляється скрізь, де він зустрічається в аргументах команди, а не тільки в аргументах, де він один, як у деяких версіях find. …

-exec command {} +

      Цей варіант -execдії виконує задану команду на вибраних файлах, але командний рядок будується додаванням кожного вибраного імені файлу в кінці; загальна кількість викликів команди буде значно меншою, ніж кількість відповідних файлів. …


12

На додаток до відповіді тердона,

  • "Очевидно" -exec …треба закінчувати крапкою з комою ( ;) або знаком плюс ( +). Кома спеціальний символ в оболонці (або, принаймні, кожен обстрілювати я коли - небудь використав), тому, якщо він буде використовуватися як частина findкоманди , він повинен бути екранований або цитований ( \;, ";"або ';').
  • З -exec … ;, {}рядок може з'являтися в команді будь-яку кількість разів, включаючи нуль або два або більше, в будь-якому положенні.  Дивіться це для прикладу того, чому ви можете зробити це -execбез використання {}.   Наявність двох або більше виступів корисно головним чином, оскільки, принаймні, у деяких версіях find, {}не потрібно бути словом само по собі; він може мати інші символи на початку чи в кінці; наприклад,

    find . -type f -exec mv {} {}.bak ";"
    

    З -exec … +, {}рядок повинен бути останнім аргументом перед +. Така команда

    find . -name "*.bak" -exec mv {} backup_folder +
    

    приводить до загадкового find: missing argument to ‘-exec’повідомлення про помилку.

    • Вирішення цього, характерного для команд cpта mvкоманд, є

      find . -name "*.bak" -exec mv -t backup_folder {} +
      

      або

      find . -name "*.bak" -exec mv --target-directory=backup_folder {} +
      

    {}Повинно бути слово само по собі; він не може мати інших символів на початку чи в кінці. І, принаймні, у деяких версіях програми findви можете мати не одну {}.

  • Санітарна примітка: Ви можете сказати

    знайти. -name "* .sh" -тип f -executable -exec {} необов'язкові аргументи тут ";"

    для запуску кожного зі своїх сценаріїв. Але

    знайти. -name "* .sh" -тип f -executable -exec {} +

    запускає один із ваших сценаріїв, імена всіх інших як параметри. Це схоже на висловлювання

    ./*.sh
    

    як команда оболонки, за винятком випадків find, не гарантує сортування її результатів, тому вам не гарантується запуск aaa.sh (ваш алфавітний перший *.shфайл), як це було б із запуском ./*.sh.

  • Аспект, findякий може бути не зовсім зрозумілим для початківців, полягає в тому, що командний рядок - це фактично виконуваний вислів на мавній мові. Наприклад,

    find . -name "*.sh" -type f -executable -print
    

    засоби

    for each file
        if the file’s name matches `*.sh` (i.e., if it ends with `.sh`)
        then
            if it is a plain file (i.e., not a directory)
            then
                if it is executable (i.e., the appropriate `---x--x--x` bit is set)
                then
                    print the file’s name
                end if
            end if
        end if
    end loop
    

    або, просто,

    for each file
        if the file’s name matches `*.sh`  AND  it is a plain file  AND  it is executable
        then
            print the file’s name
        end if
    end loop
    

    Деякі -ключові слова є і виконаною дією, і тестом. Зокрема, це стосується -exec … ;; наприклад,

    find . -type f -exec grep -q cat {} ";" -print
    

    перекладається на

    для кожного файлу
        якщо це звичайний файл (тобто не каталог)
        потім
            виконати grep -q cat filename
            якщо процес успішний (тобто, виходить зі статусом 0)
            потім
                роздрукувати ім'я файлу
            закінчується, якщо
        закінчується, якщо
    кінцева петля

    який буде друкувати імена всіх файлів, що містять рядок " cat". І, хоча це щось, що grepможна зробити самостійно (за допомогою -l(нижнього регістру L) опції), це може бути корисно використовувати findдля пошуку файлів, що містять певний рядок І мають певний розмір І належать певному власнику І були змінені в певний часовий діапазон,….

    Однак це не працює -exec … +. Оскільки -exec … +виконується одна команда для декількох файлів, не має сенсу використовувати її як логічну умову всередині for each file …циклу.

  • Зворотний бік вищезазначеного полягає в тому, що, findяк правило, виходить зі статусом виходу 0, якщо ви не наводите його недійсні аргументи, або якщо він не зустрічає каталог, який він не може прочитати. Навіть якщо програма, яку ви виконуєте, не працює (виходить із ненульовим статусом виходу), findвийде зі статусом виходу 0.  За винятком випадків,  коли програма, яку ви виконуєте зі -exec … +збоєм (виходить із ненульовим статусом виходу), findвийде з ненульовим статусом виходу.

На додаток до мільйона версій find(1) та тестування того, що findнасправді працює в декількох системах, Технічні вимоги до відкритої групи випуску 7, видання 2013 року надали частину інформації про те, що findпотрібно, що може, а що не потрібно робити.


3
Слідкуйте за тим, щоб ваш приклад ... -exec mv {} {}.bak ...не мав гарантії працювати, як очікувалося, у всіх findреалізаціях. Стандартні стани POSIX {}повинні з'являтися окремо, щоб завжди їх розпізнавати, інакше поведінка вільна, щоб символи залишалися незмінними або замінювали їх на ім'я шляху. У першому випадку вся ваша команда фактично видалить усі файли, але останній знайдений ...
jlliagre
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.