0

This question already has an answer here:

I have a *.sh script that's missing the shebang from the first line. Can I fix it with sed?

marked as duplicate by don_crissti, G-Man, Jeff Schaller, Satō Katsura, roaima Sep 28 '16 at 20:30

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

2

Insert (i) the shebang with sed, in place operation:

sed -i '1 i #!/bin/bash' file.sh

With backing up the original file with a .bak extension:

sed -i.bak '1 i #!/bin/bash' file.sh

Replace #!/bin/bash with actual shebang you want.

Example:

% cat foo.sh
echo foobar

% sed '1 i #!/bin/bash' foo.sh 
#!/bin/bash
echo foobar
  • Just curious, could you get it working on empty files too somehow? – rudimeier Sep 28 '16 at 19:40
  • @rudimeier Not of my knowledge, no. – heemayl Sep 28 '16 at 19:44
  • could do something like: if [[ -z $(<file.sh) ]] ; then echo '#!/bin/bash' > file.sh ; else sed '1 i #!/bin/bash' file.sh ; fi – Stephan Sep 28 '16 at 19:55
  • 1
    @Stephan If you want like that, just do: sed '1 i #!/bin/bash' file.sh || echo '#!/bin/bash' > file.sh – heemayl Sep 28 '16 at 19:59
  • The downside to that approach is it will overwrite the contents of file.sh if the sed command fails for any reason (I/O issue, for example.) But yah, that's the general concept I was suggesting. – Stephan Sep 28 '16 at 20:01
2

Using bash and cat (not in-place):

cat <(echo '#!/bin/sh') foo.sh

Or in-place using GNU awk >= 4.1:

awk -i inplace 'BEGINFILE{print "#!/bin/sh"}{print}' foo.sh

  • For the first one { echo '#! /bin/sh -'; cat foo.sh; } or echo '#! /bin/sh -' | cat - foo.sh would make it more straightforward (and portable) (and more efficient for the first one) IMO – Stéphane Chazelas Sep 28 '16 at 20:34
  • @Stéphane Chazelas: thx, regarding { echo '#! /bin/sh -'; cat foo.sh; }, this was my first version but I hate using cat (concatenate) for only one file. In zsh it would work like this { echo '#! /bin/sh -'; <foo.sh; }. Nothing similar is portable I guess. However I think I should remove my non-inplace version since OP wants to edit the file. – rudimeier Sep 28 '16 at 20:43
  • Note that zsh's <foo.sh actually calls pager < foo.sh – Stéphane Chazelas Sep 28 '16 at 20:59
  • @rudimeier Thanks for these alternative solutions. If the first one works, I could probably just add something like; >foo-1.sh to the end, no?. – tjt263 Oct 3 '16 at 11:25
  • @tjt263 No, this does not work in general. See unix.stackexchange.com/questions/36261/… – rudimeier Oct 4 '16 at 9:55

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