Чтобы ответить на ваши точные вопросы:
почему он выводит путь? когда 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"
Не найдено дубликатов ... обратитесь к руководству FreeBSD , в котором приводится достаточно веская причина:
Оператор exec
заменяет процесс оболочки указанной программой. Еслиexec
опущено, процесс оболочки остается в памяти, пока программа выполняется, и без необходимости потребляет системные ресурсы.
, который, по сути, является причиной, объясненной мне некоторое время назад (одним из носильщиков), и довольно хорошо известен.
Использование exec
делает обертку более прозрачной, т.е. снижает вероятность того, что пользователь или приложение, вызывающее скрипт, должны знать, что это ретранслятор, который в свою очередь запускает "настоящую" программу.
В частности, если вызывающая программа захочет убить программу, она просто убьет процесс, который только что запустила. Если сценарий-обертка запускает дочерний процесс, вызывающая сторона должна знать, что ей следует выяснить дочерний процесс обертки и убить его вместо этого. Сценарий обертки может установить ловушку для передачи некоторых сигналов, но это не будет работать с SIGSTOP или SIGKILL, которые нельзя перехватить.
Вызов exec
также экономит немного памяти (и других ресурсов, таких как PID и т.д.), поскольку нет необходимости держать вокруг себя дополнительный shell, которому нечего делать.
Если оболочек несколько, то проблем становится больше (трудности с поиском нужного процесса для уничтожения, затраты памяти и т.д.).
Некоторые оболочки (например, оболочка Korn) автоматически определяют, когда команда является последней и нет активной ловушки, и ставят неявный exec
, но не все (например, не bash).