15

Is there any way to set +x bit on script while creating?

For example I run:

vim -some_option_to_make_file_executable script.sh

and after saving I can run file without any additional movings.

ps. I can run chmod from vim or even from console itself, but this is a little annoying, cause vim suggests to reload file. Also it's annoying to type chmod command every time. pps. It would be great to make it depending on file extension (I don't need executable .txt :-) )

24

I don't recall where I found this, but I use the following in my ~/.vimrc

" Set scripts to be executable from the shell
au BufWritePost * if getline(1) =~ "^#!" | if getline(1) =~ "/bin/" | silent !chmod +x <afile> | endif | endif

The command automatically sets the executable bit if the first line starts with "#!" or contains "/bin/".

| improve this answer | |
  • 1
    Wow, that's great thing. Btw, seems you can join two if's into one if getline(1) =~ "^#!/bin/". Anyway that's amazing. Thank you. – rush Jun 4 '12 at 13:39
  • This is not a "or". I prefer to use just first condition, au BufWritePost * if getline(1) =~ "^#!" | silent !chmod +x % | endif – vault Feb 17 '16 at 14:39
  • 1
    @rush The reasons for the double if statements is to to catch lines where the the /bin doesn't immediately follow the shebang, like #!/usr/bin/env. A way around that is of course to use a wildcard: getline(1) =~ "^#!.*/bin/". – Harald Nordgren Apr 2 '16 at 14:47
  • 2
    Neat trick but I get the following every time I save: written/bin/bash: endif: command not found /bin/bash: endif: command not found – StevieD Feb 10 '17 at 21:36
  • 3
    this fixes it: au BufWritePost * if getline(1) =~ "^#!" | if getline(1) =~ "/bin/" | silent execute "!chmod a+x <afile>" | endif | endif – StevieD Feb 10 '17 at 21:44
4

I found this script at http://vim.wikia.com. Not a perfect solution, but a acceptable one, I think.

function! SetExecutableBit()
  let fname = expand("%:p")
  checktime
  execute "au FileChangedShell " . fname . " :echo"
  silent !chmod a+x %
  checktime
  execute "au! FileChangedShell " . fname
endfunction
command! Xbit call SetExecutableBit()

You can now set the execute bit with the command :Xbit. All credit to Max Ischenko at vim.wikia.com

| improve this answer | |
0

I use this in MacVim Custom Version 8.0.648 (134)

" if file is executable just exit

au BufWritePost *.sh if FileExecutable("%") | if getline(1) =~ "^#!" | silent !chmod u+x % | endif | endif

" Determines if file is already executable 

function! FileExecutable(fname)

    execute "silent! ! test -x" a:fname
    return v:shell_error

endfunction
| improve this answer | |
0

tonymac's answer stopped working for me at some point (with VIM 7.4), giving me the same problem as @StevieD. Modifying it fixed the problem:

au BufWritePost * if getline(1) =~ "^#!" | if getline(1) =~ "/bin/" | silent execute "!chmod +x <afile>" | endif | endif

I found the answer from https://bbs.archlinux.org/viewtopic.php?id=126304, although @StevieD also gave the same answer.

| improve this answer | |

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.