1

I use GNU Emacs 24.3.1 on Ubuntu 14.04 and I have a bash script: ~/path/to the/script/test.sh. As you see the path has space character. Script has a simple content:

ENTRY=`zenity --password --username`

When I try to run script from Emacs by C-c C-x(execute script option from Sh-Script menu), without marking any region, I got this error:

/bin/bash: ~/path/to: No such file or directory

Comint exited abnormally with code 127 ...

But when I try to run that from bash, it runs normally:

~/path/to\ the/script/test.sh

So I'm sure the problem is in about space character in path of script. Also I do not want to change the path (by removing space and for example replacing it by '_') because it is a part of a nested/linked content manager system and changing it may cause a big problem. Is there a way to solve this problem without changing path of script?

  • 1
    What command do you have bound to C-c C-x? That's not a key which is customarily bound to some common command. – db48x Nov 6 '16 at 19:12
  • Sounds like you need to shell-quote. I suspect that this is a duplicate question, but I don't have the time now to search. – Drew Nov 6 '16 at 19:55
  • @db48x I did not understand what you mean:What command do you have bound to C-c C-x? but I did not mark (select) any text in script. Also I edited my question, please see it again. – hasanghaforian Nov 7 '16 at 3:28
  • Oh, I understand now. You're in sh-mode, which does indeed bind a command to the C-c C-x shortcut (specically the executable-interpret command). It looks like this command has a bug which should be reported with M-x report-emacs-bug, but we can probably also work around. I'll make the work-around into an answer. – db48x Nov 7 '16 at 4:03
2

Assuming that ctrl-c ctrl-x is bound to execute-interpret, then the system should prompt you with the command to run, suggesting as a default /path/to the/script/test.sh as a default. Edit this default value to put single quotes around the whole thing.

A different way would be to change the command to be run to ./test.sh. I suspect that when you say But when I try to run that from bash, it runs normally. you are actually running this command, not the one emacs offers you by default.

You might consider adding some setting of file variables to the end of the file, e.g.

 #!/bin/bash

 echo Hello there
 ....

 # Local Variables:
 # mode: sh
 # executable-command: "'/path/to the/script/test.sh'"
 # End:

This will query you if you want to set the variable when you load the file.

1

Here's the workaround that I mentioned:

(defun db48x/shell-quote-arg-list (args)
  (mapcar 'shell-quote-argument args))

(advice-add 'executable-interpret :filter-args 'db48x/shell-quote-arg-list '(name escape-command-name))

This tells emacs to run the db48x/shell-quote-arg-list function on the argument list any time anyone calls executable-interpret. This gives us a change to escape any spaces in it before it's passed off to the original function.

This works quite well; any spaces or shell metacharacters you give to executable-interpret are escaped, and everything works quite well.

There is one downside, however. The next time you run executable-interpret, it will reuse the same value again as the new default script to run. However, it saved the value after we escaped it, so if you use it as-is it will be escaped again. A more complex set of advice needs to be applied to get the right behavior, probably an :around function that escapes the argument, calls the original function, and then overwrites the variable holding the previous command with the unescaped version.

Edit:

Here's the better method I mentioned:

(defun db48x/executable-interpret-escaped (original-func command)
  (funcall original-func (shell-quote-argument command))
  (setf executable-command command))

(advice-add 'executable-interpret :around 'db48x/executable-interpret-escaped '(name escape-command-name))
  • Excuse me because I'm beginner. Where I have to do edit/add defun ...? What must be values? Any link that describe is preferred. Also does that saves the value and use it for all other scripts? – hasanghaforian Nov 7 '16 at 6:46
  • Add them to your ~/.emacs/init.el file. This file is run on startup and is where most of your customizations will end up. – db48x Nov 7 '16 at 7:10
  • @db48x, The problem with this approach is now you can no longer pass arguments to the script. They are merged into the filename. What I think is needed is to raise a bug report to change the (or executable-command buffer-file-name) to (or executable-command (shell-quote-argument buffer-file-name)). – icarus Nov 7 '16 at 7:32
  • Yes, that's reasonable as well. Harder to define advice for though. – db48x Nov 7 '16 at 8:08
  • @db48x I think the proposed way by ` icarus` is simpler, at least for beginners. But thank you for your reply! – hasanghaforian Nov 7 '16 at 18:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.