В Emacs- lisp, каков правильный способ использования call-процесса в команде ls?

Я хочу выполнить следующую команду оболочки в emacs- lisp:

ls -t ~/org *.txt | head -5

Моя попытка:

(call-process "ls" nil t nil "-t" "~/org" "*.txt" "| head -5")

приводит к

ls: ~/org: No such file or directory
ls: *.txt: No such file or directory
ls: |head -5: No such file or directory

Любая помощь будет принята с благодарностью.

Ответ 1

Проблема заключается в том, что токены типа ~, * и | не обрабатываются/не расширяются программой ls. Поскольку токены не обрабатываются, ls ищет файл или каталог, буквально называемый ~/org, файл или каталог, буквально называемый *.txt, и файл или каталог, буквально называемые | head -5. Таким образом, вы получили сообщение об ошибке "Нет такого файла или каталога".

Эти токены обрабатываются/расширяются оболочкой (например, Bourne shell/bin/sh или Bash/bin/bash). Технически интерпретация токенов может быть специфичной для оболочки, но большинство оболочек интерпретируют по меньшей мере некоторые из тех же стандартных жетонов одинаково, например. | означает объединение программ друг с другом по концам почти всем оболочкам. В качестве контрпримера оболочка Bourne (/bin/sh) не выполняет расширение ~ tilde/home-directory.

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

/bin/bash -c "ls -t ~/org *.txt | head -5"

так

(call-process "/bin/bash" nil t nil "-c" "ls -t ~/org *.txt | head -5")

Изменить: Уточнены некоторые проблемы, например, что /bin/sh не выполняет расширение ~.

Ответ 2

В зависимости от вашего варианта использования, если вы хотите, чтобы вы выполняли команды оболочки и часто делали вывод в новом буфере, вы также можете использовать функцию shell-command. В вашем примере это выглядит примерно так:

(shell-command "ls -t ~/org *.txt | head -5")
Тем не менее, для установки этого в текущий буфер потребуется установить current-prefix-arg вручную, используя что-то вроде (universal-argument), которое немного взломано. С другой стороны, если вы просто хотите получить какой-то результат, вы можете его получить и обработать, shell-command будет работать так же хорошо, как и все остальное.