причина использования exec в сценариях оболочки

Чтобы ответить на ваши точные вопросы:

почему он выводит путь? когда ls внутри каталога просто печатает файл (это то, что я хочу)

Он выводит путь, потому что вы , а не внутри каталога. ls somedir отличается от cd somedir; ls .

почему выходной файл не в алфавитном порядке (снова сравните с ls внутри каталога - это кажется случайным)

ls помещает файлы в алфавитном порядке, а затем выводит их все . Таким образом, у него есть возможность отсортировать их перед печатью.

Когда вы используете find с -exec и завершаете команду с помощью \; , вы явно указываете find запустить один команда (в данном случае одна команда ls ) для каждого файла, найденного с помощью find . Таким образом, нет возможности их отсортировать.

Если вы использовали ls -l , вы также заметили бы, что столбцы были неправильно выровнены, поскольку каждая напечатанная строка фактически выводится из другой команды.

Вместо этого вы можете использовать find ... -ls или find ... -print , или, если действительно необходимо, использовать -exec ls , вы можете использовать -exec ls {} + , который должен обрабатывать сортировку по большей части.(В частности, вероятно, что все файлы будут отсортированы вместе, но если их так много, что оно превышает ARG_MAX вашей системы, тогда find будет вынужден использовать отдельные ls и эти отдельные пакеты будут отсортированы отдельно.)


Примечание: Я лично никогда не стал бы сохранять такой список имен файлов в текстовый файл, потому что имена файлов могут содержать символы новой строки. Не существует надежного способа разобрать текстовый файл на отдельные имена файлов. Период. (См. Почему не parse ls ? )

Вместо этого я бы просто запустил команду find , когда мне нужно сделать что-то с файлами, а не запускать это заранее, а затем пытаться что-то сделать с более ранним выводом.

Если бы я хотел создать удобочитаемый список всех моих файлов mp4 , я бы подчеркнул, что на них нельзя полагаться как на имена файлов, удалив компоненты пути:

find "/volume1 HD FILMS" -iname "*.mp4" -type f -print | sed 's:.*/::;s/\.[mM][pP]4$//' > "/volume1/3. HD FILMS/HD_FILMS_$(date +%d.%m.%Y).txt"

28
02.12.2019, 10:07
2 ответа

Не найдено дубликатов ... обратитесь к руководству FreeBSD , в котором приводится достаточно веская причина:

Оператор exec заменяет процесс оболочки указанной программой. Если exec опущено, процесс оболочки остается в памяти, пока программа выполняется, и без необходимости потребляет системные ресурсы.

, который, по сути, является причиной, объясненной мне некоторое время назад (одним из носильщиков), и довольно хорошо известен.

11
27.01.2020, 19:39

Использование exec делает обертку более прозрачной, т.е. снижает вероятность того, что пользователь или приложение, вызывающее скрипт, должны знать, что это ретранслятор, который в свою очередь запускает "настоящую" программу.

В частности, если вызывающая программа захочет убить программу, она просто убьет процесс, который только что запустила. Если сценарий-обертка запускает дочерний процесс, вызывающая сторона должна знать, что ей следует выяснить дочерний процесс обертки и убить его вместо этого. Сценарий обертки может установить ловушку для передачи некоторых сигналов, но это не будет работать с SIGSTOP или SIGKILL, которые нельзя перехватить.

Вызов exec также экономит немного памяти (и других ресурсов, таких как PID и т.д.), поскольку нет необходимости держать вокруг себя дополнительный shell, которому нечего делать.

Если оболочек несколько, то проблем становится больше (трудности с поиском нужного процесса для уничтожения, затраты памяти и т.д.).

Некоторые оболочки (например, оболочка Korn) автоматически определяют, когда команда является последней и нет активной ловушки, и ставят неявный exec, но не все (например, не bash).

39
27.01.2020, 19:39

Теги

Похожие вопросы