我想运行以下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-command
。 Emacs and Long Shell Commands也没有帮助我,因为compile
和comint-run
也需要命令,而不是bash语法。
如何从Elisp运行复杂的bash脚本?
答案 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 < / p>
"${_dirs_in_path[@]}"
将会结束。
答案 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的变体code和one),以确保Emacs具有相同的环境变量,包括PATH,作为shell。 / p>