Can't read file generated by bash line - c

I have written a C code where the bash script lines are used inside this C code, and this is how I wrote it:
printf("wc -l < smallerthan > number_lines\n");
if( (fr=fopen(fname_rcut,"r"))==NULL ) { printf("error in rcut file: %s\n",fname_rcut); exit(1); }
I need to read the file "number_lines" which is generated from "smallerthan" file, the problem is when I source the C code to run automatically like:
$gcc myC_code.c -lm
$./a.out > run.sh
$source run.sh
Then if I view the run.sh
& vi run.sh
I get this inside run.sh:
wc -l < smallerthan > number_lines
ls
error in rcut file: /home/number_lines
which mean the code upto this point didn't find my "number_lines" file yet since the number_lines file is yet to appear, but if I copy the line and run it separately, instead of "automatically", then it works because the file is there now.
My question is, how to make my code run automatically and my C code to read the file which is generated by bash line or how to generate the file and read it properly?
Any idea please because I'm really new to programming and I have to use bash inside C for my work.
Note: the above is only small part of my C code but I used several bash lines inside my C code.

There are a number of observations in your code. I assume that char *fname_rcut indeed points to "/home/number_lines".
First observation: if you write commands to a file, they will not be executed.So the file number_lines is created only after you run run.sh. Therefore, the file will not exist during the execution of your C program. You might look into int system(const char *command) (man 3 system).
Second observation: /home/number_lines is probably not the correct filename. It would probably be /home/your_name/number_lines; try a pwd to see what the exact directory name is.
Third observation: Why do you want to source run.sh? Source executes the file in the current shell. There is usually no need for that.

I have solved it :
what we need actually is using system(command) after each shell command
for example :
printf("wc -l < smallerthan > number_lines\n");
will be after solving :
sprintf(command1,"wc -l < smallerthan > number_lines\n");
system(command1);

Related

passing multiple arguments that are file names from multiple txt files to a c program ran in linux terminal

I have a project that requires converting a big list of .bin files to an equivalent big list of .csv files. The converter script is already written in c by a company called agilent, the catch 22 is the script only converts one .bin file at a time. but once converted, it will be in the correct format for my project
The c program (called agilent_bin_reader.c) works fine when I type the arguments manually, but when the arguments come from a .txt file then the file opener fails to open the file. I want to automate the process to run the c program thousands of time so I created a script.sh that repeats the process until EOF of either one of the txt files.
Manually entered Example) linux_shell$ ./agilent_bin_reader des_trace1.bin trace1.csv
Saves the binary information from des_trace1.bin into trace1.csv perfectly.
My problem is when I run this c program using my script.sh I get the error that the file basically failed to open. Its a problem with this part of the c code:
inputFile = fopen(argv[1], "rb");
if (inputFile)
because the if never evaluates to true. the else that follows basically kicks me out of the code.
Heres my script.sh that Ive created:
while
IFS= read -r a1 <&3 &&
IFS= read -r a2 <&4
do
./agilent_bin_reader "$a1" "$a2" 3<&- 4<&-
done 3< names1.txt 4< names2.txt
As one can see, the arguments here are names1.txt and names2.txt as they pass into argv[1] and argv[2] respectively. But even though the arguments are perfectly set up, its almost like the fopen thinks it should be looking in the names1.txt file for the .bin file but really the .bin files are sitting in the same folder as agilent_bin_reader.c, names1.txt, and names2.txt. There shouldnt be any issues with directories unless my script.sh makes the fopen only look at the .txt file that the argv[] goes into.
I want the code to do this basically:
linux_shell$ ./agilent_bin_reader names1.txt(1st line) names2.txt(1st line)
linux_shell$ ./agilent_bin_reader names1.txt(2nd line) names2.txt(2nd line)
linux_shell$ ./agilent_bin_reader names1.txt(3rd line) names2.txt(3rd line)
....
....
linux_shell$ ./agilent_bin_reader names1.txt(81,569th line) names2.txt(81,569th line)
*EOF of both .txt files, iteration complete
My names1.txt file looks like:
des_trace1.bin
des_trace2.bin
des_trace3.bin
...
des_trace81569.bin
My names2.txt file looks like:
trace1.csv
trace2.csv
trace3.csv
...
trace81569.csv
Here is the converter code supplied to me (Is found at http://www.dpacontest.org/agilent_bin_reader.c) {I named this program agilent_bin_reader.c just like the company who created it did}
Shawn in the comments section found that my issue was my txt files had hidden characters in them.. Ran dos2unix and my problem instantly went away. See this website for a detailed explanation: https://www.liquidweb.com/kb/dos2unix-removing-hidden-windows-characters-from-files/
Here are the commands I ran:
linux_shell$ sudo apt install dos2unix
linux_shell$ dos2unix names1.txt
linux_shell$ dos2unix names2.txt

How do I apply code to all files within a folder?

I'm relatively new to programming, but created a c script to rotate images and create a copy of them. However, I was hoping to apply it to a large number of files, so I was wondering if there was a way to apply a program / function to all images within a specific folder. Thanks!
If the program gets the filenames to process in its command line arguments (the argv parameter to main()), you can use a wildcard in the command line when you run it:
yourprogram /path/to/directory/*
The program should simply loop through all the filenames in argv.
If it can only process one file at a time, you can use a shell loop:
for file in /path/to/directory/*
do
yourprogram "$file"
done
You could pass wildcards to the executable. The shell would expand the wildcard to all files it matches. Your main program could look like this:
int main(argc, char ** argv)
{
for(int arg=1; arg<argc; arg++)
doStuffToFile(argv[arg]);
}
That is the best solution if you plan to use this quite a lot. If you just need a quick fix you'd be better of with a shell script. This is how it would be done in bash:
for file in /path/*
do
[ -e "$file" ] || continue
program "$file"
done

Cannot execute binary file when calling Java from Bash

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.

Why won't this program work with the OS redirection command in C?

I am working with command prompt features with a simple program to generate a text file in C. Here is the program:
#include <stdio.h>
int main(void)
{
char buf[80];
fgets(buf, 30, stdin);
printf("the input was %s\n", buf);
return 0;
}
My programming book is wanting to show how to play with the command prompt to make text files from programs, and instructs typing the word 'redirect' followed by '>' then the name of the program name with '.txt'. as below:
redirect> programname.txt
Now this IS generating a file 'programname.txt' on the desktop, but it is empty. The book purports that recipe should allow me to enter a string (as the program is DESIGNED to do) and that this string will be inside a generated programname.txt file. Also, there is a warning in the command line: "not recognized as an internal or external command". I've had this schpill before, but the text file generation did WORK, in that it did generate the .txt file. What am I missing here, for this program to work as intended?
You seem to be confused by the fact that it is not your program, but the shell which creates the file programname.txt, before it even tries to run your program.
And after the first succeeded and created an empty file, the latter probably fails because there is no command redirect in your PATH or such a thing exists as a builtin in your shell, as has already been suggested.
The usual way to perform output redirection in a shell is to use the > filename, but not with redirect before it contrary to what you say. The thing that comes before the > is the command to be redirected.
So, let's say you compile your program and save it as foo in the current directory (e.g. cc -o foo myprogram.c). In that case, you can redirect its output by saying:
./foo > filename.txt

Redirection in Linux

Input files to test project 2. Intended to be used via redirection.
My professor gave us a txt file to use to test if our program works. It reads in ~1000 numbers (so we wouldn't have to manually enter them). But I don't know the linux command on how to use this txt file.
ccarri7#ubuntu:~/C$ ls
ccarri7lab2 ccarri7lab2.c lab2input.txt
ccarri7#ubuntu:~/C$
This is the folder where my executable/source/txt file are.
./ccarri7lab2 < lab2input.txt
will use the text in lab2input.txt as arguments for ccarri7lab2
http://linux.about.com/od/itl_guide/a/gdeitl42t01.htm
Did you try
ccarri7lab2 < lab2input.txt
Hope this is what you want, else you can give some more info.

Resources