Syntax error in .bash_profile unexpected end of file - bash

Running MacOS High Sierra 10.13.5
Good day! Today I attempted to write a script in my .bash_profile to allow me to call Sublime Text with a single command, sublime.
Here is the script I produced with my limited knowledge of bash as well as some research:
sublime_open() # Function which opens the first argument as a text file in Sublime.
{
open -a /Applications/Sublime\ Text.app < $1.txt;
}
export -f sublime_open;
sublime_test() # Function which will open first argument as a text file in Sublime,
{ # creating one if it does not exist in the current directory.
if [ -e "$1" ];
then sublime_open "$1"
else
touch "$1".txt
sublime_open("$1")
fi
}
export -f sublime_test
alias sublime="sublime_test"
export sublime
I separated the function into two pieces for the sake of readability.
Expected Behavior:
sublime foo opens an instance of Sublime to the file foo.txt, creating that file if it does not already exist.
Observed Behavior:
Bash returns:
line 29: syntax error: unexpected end of file
Note that line 29 is the line after the file's final line, which does not exist.
Attempts at solution:
So far I have searched for solutions here and here.
I have tried:
Copying over to a new bash profile and deleting the old one to remove "ghost" characters
Running dos2unix on my .bash_profile
Parsing the script myself looking for individual errors, the problem seems to occur in the sublime_open() portion.
Sorry if my script is elementary or uninformed, this was my first attempt at writing a script that behaves this way. I welcome help or tips outside of the scope of my issue.
Thanks in advance!
Edit: Fixed misused heredoc as per #jwodder's solution as well as improper function calls as per #codeforester's solution.
Edit 2: If you are looking for a more elegant solution to this same problem, have a look at this very helpful gist.

The problem is this line:
open -a /Applications/Sublime\ Text.app << $1.txt;
I assume that what you mean for this to do is to feed the contents of $1.txt to Sublime Text on standard input. However, that would be done with one <, not two. With two <, you get a heredoc, which means that bash will look for the next line containing just $1.txt and will use all lines in between as the input to Sublime Text. As the file ends before bash finds a line with just $1.txt, you get an "unexpected end of file" error.

Keep in mind that on macOS, an *.app is just a folder. Generally speaking, you need to specify the location to a binary (or script). In the case of Sublime Text you have to use the Sublime Text CLI tool:
/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl
See the OS X Command Line documentation for details.

Related

Here Document to interact with VI

I was just trying to figure out EOF and here documents. I read something online that seemed like a cool idea I could expand upon. It is supposed to create a text file, and add text to it, all using a here document. The syntax is as follows:
#!/bin/sh
filename=test.txt
vim $filename <<EndOfCommands
i
This file was created automatically from
a shell script.
^[
ZZ
EndOfCommands
Now unfortunately I get an error from this:
./EOF.sh
Vim: Warning: Input is not from a terminal
Vim: Error reading input, exiting...
Vim: Finished.
Can anyone help fix this error? Also im assuming ^[ stands for the escape button being hit?
vi and vim are meant to be used interactively in a terminal, not scripted.
Using ed instead, which can happily accept input from standard input sources of all types:
#!/bin/sh
filename=test.txt
ed -s "$filename" <<EndOfCommands
i
This file was created automatically from
a shell script.
.
w
EndOfCommands
(In insert mode, a line with a single period indicates end-of-input and goes back to command mode, kind of like escape in vi(m).)
Using ex is another option; on systems with vim installed it's often a non-visual version of it.
With vim:
filename="test.txt"
vim -c ":wq! $filename" - << EOF
This file was created automatically from
a shell script.
EOF
See: man vim

Cygwin on Windows 7 (64bit): No such file or directory - but 'which' does give me the correct path

A formely working bash script no longer works after switching computers. I get the following error:
No such file or directory.
Before going on, please excuse any mistakes you may find since english is not my native language.
The script was used in cygwin under Windows XP. I now had to switch to cygwin64 under Windwos 7 (64bit).
The script is used as a checkhandler for the program SMSTools3 to split a file with a specific format into multiple smaller ones, which the program then uses to send SMS to multiple recipients. The script was copied directly from the page of SMSTools3 and uses the package formail.
After looking up the error the most likely problem was that the environmantle path was not set up to look in the right path (/usr/bin). I therefore added it to the path but to no avail.
I then deleted other entries in the enviromental path of windows which contained spaces because that could have been another explanation, but again to no avail.
Following is a minimal example of the code which produces the error.
#!/bin/bash
# Sample script to allow multiple recipients in one message file.
# Define this script as a checkhandler.
echo $PATH
which formail
outgoing="/var/spool/sms/outgoing"
recipients=`formail -zx "To:" < "$1"`
I added the lines the lines echo $Path and which formail to show if the script can find the correct file. Both results look fine, the second command gives me the right output '/usr/bin/formail'
But the line recipients=... throws me the error:
No such file or directory.
I do not have much experience with bash scripting, or cygwin in general. So if someone on this wonderful board could help me solve this problem, I would be really grateful. Thank you all for your help.
EDIT:
First of all thank you all for your comments.
Secondly, I would like to apologize for the late reply. The computer in question is also used for other purposes and my problem is part of a background routine, so I have to wait for "free time" on the pc to test things.
For the things #shellter pruposed: The ls command returned an error: '': No such file or directory.
The which -a formail as well as the echo $(which -a formail) commands that #DougHenderson pruposed returned the 'right' path of /usr/bin/formail. echo \$1 = $1 before the recipent line returned the path to the checkhandler file (/usr/local/bin/smsd_checkhandler.sh), the same command after the recipent line seems to show a empty string ($1 = ). Also, the pruposed change to the recipent line did not change the error.
For the dos2unix conversion that #DennisWilliamson pruposed, I opened the file in notepad++ to use their build in converion, but it showed me that the file is in unix format with Unix style line endings.

bash "command not found" - is my PATH wrong [duplicate]

This question already has answers here:
Bash script prints "Command Not Found" on empty lines
(17 answers)
Closed 2 years ago.
I'm using bash for the first time. Wrote a code that is supposed to take "stats" as a command, but whenever I use "stats" in my command lines I kept getting the following error:
bash: stats: command not found
I googled around and a lot of people are saying this error is usually associated with PATH problems. Running "echo $PATH" yields the following results:
/bin:/sbin:/usr/local/bin:/usr/bin:/usr/local/apps/bin:/usr/bin/X11:/nfs/stak/students/z/myname/bin:.
I made sure my program started with
#!/bin/bash
Is my PATH wrong? If so, how do I fix it? If not, any suggestions on what else I should look into? Thank you all for your time and help.
It might be a PATH problem, it might be a permission problem. Some things to try.
1) If stats is not in your current directory, change directory (cd) to the directory where stats is and do
bash stats
If stats executes correctly, then you know at least that the script is OK. Otherwise, look at the script itself.
2) Try to execute the script with
./stats
If this gives
bash: ./stats: Permission denied
Then you have a permission problem. Do a
chmod a+rx stats
and retry. Note: a+rx is perhaps a bit wide; some may suggest
chmod 755 stats
is a better choice. Hint: from the comments, I see that this is one of your problems.
3) From the name of the directory, I get the impression that the file is on NFS. It might therefore be mounted as 'noexec', meaning that you cannot execute any files from that mount. You might try:
cp stats /tmp
chmod 700 /tmp/stats
/tmp/stats
4) Check the full path name for stats. If you are still in the same directory as stats, try
pwd
Check if this directory is present in the PATH. If not, add it.
export PATH=$PATH:/nfs/stak/students/z/myname/344
and try stats again.
Your PATH looks reasonable. PATH problems are a common source of errors like this, but not the only one.
The error message ": No such file or directory" suggests that the script file has DOS/Windows-style line endings (consisting of a carriage return followed by linefeed) instead of unix-style (just linefeed). Unix programs (including shells) tend to mistake the carriage return for part of the line, causing massive confusion.
In this instance, it sees the shebang line as "#!/bin/bash^M" (where "^M" indicates the carriage return), goes looking for an interpreter named "/bin/bash^M", can't find it, and prints something like "/bin/bash^M: No such file or directory". Since the carriage return makes the terminal return to the beginning of the line, ": No such file or directory" gets printed on top of the "/bin/bash" part, so it's all you see.
If you have the dos2unix program, you can use that to convert to unix-style line endings; if not, there are a variety of alternate conversion tools. But you should also figure out why the file has Windows/DOS format: did you edit it with a Windows editor, or something like that? Whatever caused it, you should make sure it doesn't happen again, because Windows/DOS format files will cause problems with most unix programs.

Copying .jpg file using shell script gives 'Failed to open input stream for file' error

Very simple script to copy a file
#!/bin/bash
#copy file
mtp-getfile "6" test2.jpg
I set it as executable and run it using
sudo sh ./test.sh
It gives me a file called test2.jpg that has no icon and I cannot open I get a 'Failed to open input stream for file' error
However, if I simply issue the following from the command line
mtp-getfile "6" test2.jpg
It works as expected. What is wrong with my script? I checked and the resulting .jpg file in each case has the same number of bytes. Very strange.
As commented by chepner, your file might have a DOS (Windows) invisible line ending on its name, which would cause an error. To get rid of this unwanted character(s), just create a new blank script on your "nix" system and type the name by hand (not by copying and pasting, to avoid problems), let's say, name it test2.sh.
Then copy all the contents of test.sh to test2.sh (copy and paste) and run test2.sh and see if it works. If it doesn't, try running the following code on the new script, to make sure that there are no unwanted characters on the code itself:
tr -d "\r" < /folder/test2.sh && echo >> /folder/test2.sh
And then try to run script2.sh again to see if it works. Note: the echo >> /folder/test2.sh part of the code above is just to make sure that your new script ends with a newline, which is a Posix standard (and without which some programs may misbehave because they expect the file to end with a newline).
Apparently it was a permissions issue.
I only had to do a sudu chown test2.jpg

Pipe between two text files in BASH

I'm new to all this(one day old bash coder) so as much as stupid this question might sound, please take your time and respond accordingly :)
I created a script in BASH that should do some things to a given input(which is a text file). I'm having some hard time trying to figure out how to use pipeline to run the script(which is called cleanLines, for the sake of the question) on a text file (named test.txt) so that it'll "clean his lines".
I added the below line of code to the top of my script file(cleanLines):
PATH=${PATH[*]}:.
Now what?
./test.txt | ./cleanLines.txt
Doesn't seem to work.
I should note that the files are in the same directory, if that worths anything to you.
EDIT: Oh and cleanLines is also a text file(.txt).
And it gives me the error:
-bash: ./cleanLines.txt: Permission denied
A pipe | redirects the output of a command, but test.txt is not a command. You can read more about redirection here or here. To redirect input from a file you would do this instead:
cleanLines < test.txt
This assumes that your script is executable and expecting input from standard input.

Resources