2012-07-26 17 views
5

.shファイルではなく、Elisp文字列に格納された次のbashスクリプトを実行して、シェル出力を変数に格納します。複数文字列のbashスクリプトをEmacsから実行する

#!/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は、compilecomint-runにもbashの構文ではなくコマンドが必要なので、どちらも役に立ちませんでした。

私はElispから複雑なbashスクリプトを実行するにはどうすればよいですか?

+0

のMxシェルコマンドで領域が失敗した場合バグ報告を送ってください –

答えて

6

複数行のコマンドは、例えば、あなたがシェルのメタキャラクタを含む可能性のある他のシェルの引数と同じようにあなたがそれらを引用する場合bash -cへの引数として提供するために細かいです:

(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))) 
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))) 

EDITああを追加し、そして、ファイル名にセパレータとして扱われるかもしれないスペースや他の文字を持っている場合FYI "${_dirs_in_path[@]}"は悪い終了する予定です。

+0

いいえ、$ {arrayvar [@]} "構文は、' arrayvar'の要素にあるシェルメタキャラクタの存在にかかわらず、完全に安全です。 – Sean

0

shell-commandは実際にはマルチストリングbash構文で動作します。私の問題は、shell-commandはPATHを含むbash環境変数を知らないということでした。私がしたこと:"をすべてスクリプトの\"に置き換え、それを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))) 

私はまだあまりにも多列のbashスクリプトでcompile仕事を作成する方法に興味があります。 PATH上

注:限り、私は理解し、do not run shell before Xsession(XDM、GDMとKDMを含む)Xディスプレイマネージャは、そのGUIから実行Emacsが異なっています、ので、私は上記の溶液中で(getenv "PATH")を使用していませんでした環境変数はbashからのものです。私は起動時にemacs --daemonをcronで実行します。私のパスは/etc/profile~/.profileに設定されているので、EmacsはそこからPATHを取得しません。

スティーブ・パーセルは、EmacsがシェルとしてPATHを含むと同じ環境変数を、持っていることを確認する(SO上でもバリアントone、それのtwoを参照)codeを提案しています。

関連する問題