从Emacs运行多字符串bash脚本

时间:2012-07-26 09:09:18

标签: shell emacs elisp executable

我想运行以下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

我无法在包含多个字符串的bash脚本上运行shell-commandEmacs and Long Shell Commands也没有帮助我,因为compilecomint-run也需要命令,而不是bash语法。

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

3 个答案:

答案 0 :(得分: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)))

答案 1 :(得分: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)))

编辑哦,如果文件中有空格或其他字符可能会被视为名称中的分隔符,那么FYI "${_dirs_in_path[@]}"将会结束。 < / p>

答案 2 :(得分: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){{3因此,从GUI运行的emacs将具有与bash不同的环境变量。我在启动时通过cron运行emacs --daemon,我的路径设置在/etc/profile~/.profile中,因此Emacs不会从那里获取其路径。

史蒂夫·珀塞尔提出了一个do not run shell before Xsession(另请参见SO的变体codeone),以确保Emacs具有相同的环境变量,包括PATH,作为shell。 / p>