I'm a student and this is my first exposure to bash scripting, besides messing with a simple Makefile for c.
#!/usr/bin/sh
gcc -g -std=c99 -Wall -c field.c
gcc -g -std=c99 -Wall -c testField.c
gcc -g field.o testField.o -o testField
#testField get 0xa 0 1 > PA1output.txt
#testField get 0xaa 0 3 >> PA1output.txt
is my script.I want to compile field.c and testField.c into the executable testField.
No matter if I leave the last 2 lines commented out or not, they linux terminal hangs and after 10 seconds of nothing happening I press ctrl+c to stop it. Ultimately I want to redirect output to PA1output.txt, then concatenate things on the end of the file, but I want to rewrite the file contents each time.
As far as I understand it, > rewrites the contents of the specified file, and >> concatenates onto the end.
This is not my homework, I want to automate testing of other homework I have. 'testField get 0xaa 0 3 are arguments into my c program.'
I tried Bash script hangs
but that didn't answer my question totally.
My script is called 'as' to make it easy to type.
Why does the terminal hang and how do I get the script to do what I described above?
Thanks.
Your system has another program called ‘as’ which is an assembler. You are likely running this rather than your script, and it hangs because the assembler is waiting for input from your terminal.
If you insist on keeping the name, you should run your script with a full or partial pathname (like ‘./as’) so that the correct program is run.
You will probably find that your script will not run without the ‘#’ at the beginning of your first line. However, another way to run your script is ‘sh ./as’ from the command line, which does not depend on having the #! line.
As Jeremy described, it's most likely a conflict of names.
If you are running your script from the command line (I really hope you are), you don't have to be afraid of giving your scripts (and all file names for that matter) longer, but more specific, names. Most (if not all) command line interfaces on linux have some form of tab-expansion. All you have to do is type enough of the name to make it unique, then press [Tab], and the shell should complete the name for you.
Here's a more thorough explanation for Bash.
Related
This question is quit similar to Vim [compile and] run shortcut
but what I want goes a little further. Is it possible to make a shortcut which compile and run the c code in the build in terminal and leave it open afterwards? The solution in the linked post just closes the output afterwards.
I guess the trick we used when coding Turbo Pascal and Turbo C++ would solve your problems. Just add a line for some dummy user input in the end of the program.
int main(void)
{
// Your code
getchar(); // Will not return to Vim before you have entered some data
}
You can combine !g++ % -o %< and :vert term ./%< together and make it a shortcut.
Here, ! allows to run external command from vim. g++ will compile the file, % indicates the current file, < is used to remove the file extension. :vert term is an internal command that lets you use terminal within vim.
Put the code in .vimrc file in home directory. The both commands combined would like,
map <F8> :w <CR> :!g++ % -o %< <CR>:vert term ./%<<CR>
When F8 button is pressed, vim saves the file then creates the object code. Afterward, with second command vim opens a terminal and runs the program. You will have to :q or type exit to close the terminal.
Make sure to exit insert mode before you hit F8.
Essentially, I wish to call compiled C code from inside a bash script. I want to be able to call the ./a.out from any directory and have it be executed.
This all stems from something pretty simple. I made a curses program that is a screensaver for a terminal. I wish to be able to call a bash command screensaver and I want that to call the c code via bash. I want to be able to call it from anywhere in the filesystem. I am running on a 2013 Macbook but I think this is more of an infamiliarity with C issue rather than a hardware issue, I can provide more details if needed.
File is here:
/Users/User/screensaver/screensaver.c
cd /Users/User/screensaver
gcc screensaver.c creates a.out
I can then run
./a.out
And the code runs.
I have tried calling ./Users/User/screensaver/a.out among other things.
This doesn't work and it just says that the file doesn't exist. I've tried using exec and source but nothing has worked. Surely there must be a way to call this from somewhere else right? I know I could theoretically save my current directory as an environment variable, cd into the dir, ./a.out, then on quit cd back into the saved dir, but that seems like to much struggle for what its worth.
Edit: I saw that I could theoretically put it in the my bin and compiled with -o. I haven't tried it, but I don't want to do that because this code is still in development so I don't want to have to compiled and move it every time.
This worked:
"Try to invoke /Users/User/screensaver/a.out without putting a dot at the beginning of the path. There is a paticular security reason why you need to specify ./a.out rather than a.out when you are in the directory which holds the executable."
-tshiono
I'm trying to compile and run a C code while looping the input file through bash. Here is my code for the bash script I am using to automate it.
~!/bin/bash
file=1
outfile='outputnumber'$file
readsfile='readsfilename'$file'.txt'
compilefile=compiler$file'.o'
gcc -lgsl -lgslcblas -std=c99 filewithccode.c -o $compilefile
echo "Compilation over"
./$compilefile $outfile $readsfile
So what I'm basically trying to do is compile filewithcode.c so that the executable is stored as compiler1, which takes outputnumber1 and readsfilename1.txt as input. The reason I want to do this is so that I can loop it over "file" and automate it for multiple files (I have 45 of them) and automate the execution. But I'm getting the error:
Segmentation fault (core dumped) ./$compilefile $outfile $readsfile
I am trying to use different names for the compiled file because I am trying to run them parallelly on a server and I am not sure if compiling with the same output name will cause an issue.
Any suggestions? I know that maybe the "./$" is causing that error, because the BASH is echoing "Compilation over".
Your last line, being that it's just variables placed on a line might cause problems with your script being able to interpret it properly. You might try making it into a string, and then using the exec command on that string. for example:
comm="./""$compilefile $outfile $readsfile"
exec $comm
This has saved me a lot of syntax trouble with referencing variables in the past.
I have written a C program with some system command in it. I use a software called Gromacs. Here is the snippet of C code :-
#include<stdio.h>
#include <stdlib.h>
/*I have removed unnecessary code, which works fine for me. */
int main() {
float LAMBDA=0.37;
for(LAMBDA=0.37 ; LAMBDA <0.55; LAMBDA +=0.02 ) {
system("g_bar -f md*.xvg -o -oi -oh");
system("mapfile -t a < <(g_bar -f md*.xvg -o -oi -oh | sed '/lambda/s/.*DG *//')");
printf("Free Energy:\t ");
system("echo ${a[120]}");
return 0;
}
I receive an error
sh: 1: Bad substitution
I have checked previous answers on Bad substitution. It seems dash doesn't work with arrays then how can I enable Bash for system commands ? If somebody can troubleshoot me I will be grateful.
The sh vs dash vs bash is not the root problem here.
You create a 'a' (whatever that is) in your second call to system().
Then you try to use this 'a' in the forth system() call.
But this is another shell, and 'a' does not exist here.
Each time you call system(), a new shell environment is created, and disappear at return.
What you need to do is somehow save your 'a' to some file that a subsequent call may work on.
In other words, each call to system() act as if you opened a new terminal, do your stuff and then closed it. The variables created in one terminal (shell session) do not exist in the following one.
EDIT:
And to convince you that the sh/dash/bash is not your root problem here, once you've check your commands run OK when typed in the same shell session (terminal), you can always explicitly use bash in your system() calls by;
system("bash -c do_my_stuff from_this and_that etc");
First, mapfile is a bash 4 builtin command. system runs sh, not bash.
Second, and the cause of the error message, you are using process substitution here:
<(g_bar -f md*.xvg -o -oi -oh | sed '/lambda/s/.*DG *//')
sh does not support process substitution. system runs sh, not bash.
You have several calls to system. Your last call (as shown) looks at a variable a that was created in a previous shell process, it won't exist anymore!
I suggest you write a bash script, complete with #!/bin/bash, and call that from C. You could always write out the script from C, using fopen and fprintf.
If that isn't practical, the use bash -c as suggested by #jbm. But you can't expect any persistence across calls to system except via the C program.
I'm using Ubuntu 14.04.
There are 4 files involved: 'compile.sh', 'execute.sh', 'work.c', 'tester.sh'.
In 'compile.sh', it compiles the 'work.c' file and outputs an executable file called 'execute.sh'. In my own testing process, I do ./compile.sh, then ./execute.sh to run my C program. This works.
Now, the 'tester.sh' is a script that calls a Java program and this Java program does the same thing. It will run my 'compile.sh' first and then excute 'execute.sh'. It checks the correctness of my program outputs.
The problem is that when I do ./tester.sh, I get the error below
Reading first line from program...
./execute.sh: ./execute.sh: cannot execute binary file
First line of execution should match: Created \d heaps of sizes .+
Failed to execute (error executing ./execute.sh)
You can ignore the third line "First line of execution...."; it tries to check whether my output matches exactly with the tester. Since the binary file cannot be executed, then the first line does not match for sure.
So why does it say "cannot execute binary file"?
Content in compile.sh
#!/bin/bash
gcc -Wall work.c -o execute.sh
Content in tester.sh
#!/bin/bash
java -cp bin/tester.jar edu.ssu.cs153.work1.Tester
(bin/tester.jar is in my local machine; we can assume there is nothing wrong with the tester script.)
Diagnosis
It is weird, but not disallowed, to name an executable with the .sh extension. Your problem is that the Java code is trying to run it as a shell script (e.g. bash ./execute.sh), and it isn't a shell script so it fails. You need to change the Java to run the .sh file as an executable instead of as a shell script. Or, better (since you probably can't fix the Java), fix the compilation so that it produces an executable with a different name (e.g. work), and have execute.sh execute ./work.
File execute.sh is just an output file from compiling the work.c file. It is just like a.out by default from gcc. I can run ./execute.sh from the terminal and see all the correct outputs.
The trouble is, when you run it, you do ./execute.sh and the shell executes directly. The Java is running it as bash ./execute.sh, and that generates the error. Try it at the command line.
Prescription
On the face of it, you need to change compile.sh, perhaps like this (generating a program work from work.c):
#!/bin/bash
gcc -o work -Wall work.c
And you write a shell script called executable.sh that reads:
#!/bin/bash
exec ./work "$#"
This script runs your program with any command line arguments it is given. The exec means the shell replaces itself with your program; there are minor advantages to doing it that way, though it'll be OK if you omit the exec from the script.