5

我想运行以下 bash 脚本,该脚本存储在 Elisp 字符串中,而不是.sh文件中,然后将 shell 输出存储在变量中。

#!/bin/bash
IFS=: read -ra _dirs_in_path <<< "$PATH"

for _dir in "${_dirs_in_path[@]}"; do
    for _file in "${_dir}"/*; do
        [[ -x ${_file} && -f ${_file} ]] && printf '%s\n' "${_file##*/}"
    done
done

我无法shell-command在由多个字符串组成的 bash 脚本上运行。Emacs 和 Long Shell 命令也没有帮助我,因为compilecomint-run需要命令,而不是 bash 语法。

如何从 Elisp 运行复杂的 bash 脚本?

4

3 回答 3

6

bash -c如果您像引用任何其他可能包含 shell 元字符的 shell 参数一样引用多行命令,则可以作为参数提供多行命令,例如:

(setq my-command
      (concat "IFS=: read -ra dirs <<<\"$PATH\"\n"
              "for dir in ${dirs[@]}; do\n"
              " echo got dir \"$dir\"\n"
              "done\n"))

(shell-command (format "bash -c %s" (shell-quote-argument my-command)))
于 2012-07-26T15:38:25.947 回答
2

这也许会做你想要的。添加修饰符来品尝:)

(defun example-multiline-shell-command ()
  (interactive)
  (with-temp-buffer
    (insert "#!/bin/bash
IFS=: read -ra _dirs_in_path <<< \"$PATH\"

for _dir in \"${_dirs_in_path[@]}\"; do
    for _file in \"${_dir}\"/*; do
        [[ -x ${_file} && -f ${_file} ]] && printf '%s\n' \"${_file##*/}\"
    done
done")
    (write-region (point-min) (point-max) "~/temp.sh")
    (shell-command "source ~/temp.sh" (current-buffer))
    (buffer-string)))

编辑哦,"${_dirs_in_path[@]}"如果文件中有空格或其他字符可能被视为名称中的分隔符,那么仅供参考。

于 2012-07-26T09:59:04.697 回答
0

shell-command实际上适用于多字符串 bash 语法。我的问题是shell-command不知道 bash 环境变量,包括 PATH。我所做的:将脚本中的所有内容替换为 elisp 字符串,然后将一些目录分配给 PATH "\"这是成功将系统中的所有可执行文件输出到*Shell Command Output*缓冲区的代码。

(let ((path "PATH='/usr/local/bin:/usr/bin:/bin'")
      (command "IFS=: read -ra _dirs_in_path <<< \"$PATH\"

for _dir in \"${_dirs_in_path[@]}\"; do
    for _file in \"${_dir}\"/*; do
        [[ -x ${_file} && -f ${_file} ]] && printf '%s\n' \"${_file##*/}\"
    done
done"))
  (shell-command (concat path ";" command)))

我仍然对如何compile使用多字符串 bash 脚本感兴趣。

关于 PATH 的注意事项:我没有(getenv "PATH")在上述解决方案中使用,因为据我了解,X 显示管理器(包括 xdm、gdm 和 kdm)在 Xsession 之前不运行 shell,因此从 GUI 运行的 emacs 将具有不同的环境变量来自 bash 的。我emacs --daemon通过 cron 在启动时运行,我的路径设置在/etc/profileand中~/.profile,所以 Emacs 不会从那里得到它的 PATH。

Steve Purcell 提出了一个代码(另请参见 SO 上的变体和变体)以确保 Emacs 具有与 shell 相同的环境变量,包括 PATH。

于 2012-07-26T10:12:00.747 回答