I wrote a program for an assignment which is supposed to print its output to stdout. The assignment spec requires the creation of a Makefile which when invoked as make run > outputFile should run the program and write the output to a file, which has a SHA1 fingerprint identical to the one given in the spec.
My problem is that my makefile:
...
run:
java myprogram
also prints the command which runs my program (e.g. java myprogram) to the output file, so that my file includes this extra line causing the fingerprint to be wrong.
Is there any way to execute a command without the command invocation echoing to the command line?
Add # to the beginning of command to tell gmake not to print the command being executed. Like this:
run:
#java myprogram
As Oli suggested, this is a feature of Make and not of Bash.
On the other hand, Bash will never echo commands being executed unless you tell it to do so explicitly (i.e. with -x option).
Even simpler, use make -s (silent mode)!
You can also use .SILENT
.SILENT: run
hi:
echo "Hola!"
run:
java myprogram
In this case, make hi will output command, but make run will not output.
The effect of preceding the command with an # can be extended to a section by extending the command using a trailing backslash on the line. If a .PHONY command is desired to suppress output one can begin the section with:
#printf "..."
Related
I have a program in which I'm trying to invoke the following command:
make run {FILE} e.g filename.txt
How can I create my Makefile so it can execute this program and accept any filename through STDIN.
My Makefile looks like the following:
run:
python execute.py --filename {ANY FILENAME}
The arguments to make are targets. There's no special relationship between run and {FILE} in your initial example. If you want to force the run prefix, it'll have to be part of the target name, instead of space separated:
run-%:
python execute.py --filename $*
I am trying to create this little program to help me, with only one command, to compile and run a C program within Ubuntu's terminal.
Trying to make it fancier, I added an argument to the bash file so I can use it for any C program I want. So this is how it is supposed to go:
Create a variable to store the name of the file
Use that variable to compile the program (to the same file name)
Use that same name to run the file.
Here is the code:
# usr/bin/bash
filename=$1
cc -o $filename "$filename.c"
./$filename.out
almost everything runs, the only problem I still have is in the last line:
./$filename.out
It doesn't seem to use the name of the variable inside the command which executes the final program.
I'm a noob at bash (let's say I haven't used it in months).
cc -o foo will output foo not foo.out. You should also double-quote the variable expansions to prevent IFS-splitting and globbing:
filename=$1
cc -o "$filename" "$filename.c" &&
./"$filename"
Apart from that # /usr/bin/bash (unlike #!/usr/bin/bash) does nothing. It's a comment. The whole thing will be run the /bin/sh, not bash (but you don't need bash, anyway).
You will need to use quotation marks:
./"$filename.out"
#!/bin/sh
filename=$1
cc -o "${filename}.out" "${filename}.c"
"./${filename}.out"
This is a reduced example of a makefile which illustrates my problem:
exec:
time (ls > ls.txt; echo $$? > code) 2> time.txt
make exec runs fine under one Linux installation:
Linux-2.6.32-642.4.2.el6.x86_64-x86_64-with-centos-6.8-Final
but it fails under my Ubuntu installation:
Linux-4.4.0-64-generic-x86_64-with-Ubuntu-16.04-xenial
and produces the message:
/bin/sh: 1: Syntax error: word unexpected (expecting ")")
No problems if I run the command time directly from the terminal.
Are there different versions of the command in different Linux installations? I need the version which allows a sequence of commands.
Make always invokes /bin/sh to run the recipe. On some systems, /bin/sh is an alias for bash which has a lot of extra extensions to the standard POSIX shell (sh). On other systems (like Ubuntu), /bin/sh is an alias for dash which is a smaller, simpler, closer to plain POSIX shell.
Bash has a built-in time operation which accepts an entire pipeline and shows the time taken for it (run help time at a bash shell command prompt to see documentation). Other shells like dash don't have a built-in time, so when you run it you get the program /usr/bin/time; run man time to see documentation. As a separate program it of course cannot time an entire pipeline (because a pipeline is a feature of the shell); it can only time one individual command.
You have various options:
You can force your makefile to always use bash as its shell by adding:
SHELL := /bin/bash
to it. I recommend adding a comment there as well describing why bash specifically is needed.
Or you can modify your rule to work in a portable way by making the shell invocation explicit so that time only has one command to invoke:
exec:
time /bin/sh -c 'ls > ls.txt; echo $$? > code' 2>/time.txt
Put a semicolon in front of "time". As is, make is trying to parse your command as a list of dependencies.
The only suggestion that worked is to force bash in my makefile:
SHELL := /bin/bash
I checked: on my Ubuntu machine, /bin/sh is really /bin/dash whereas on the CentOS machine it is /bin/bash!
Thanks!
I'm using the 'at' command in order to create 3 directories, just a dumb bash script:
#!/bin/bash
for i in {1..3}
do
mkdir dir$i
done
Everything is ok if I execute that script directly on terminal, but when I use 'at' command as follows:
at -f g.sh 18:06
It only creates one directory named dir{1..3}, taking interval not as an interval but as a list with one element {1..3}. According to this I think my mistake is using bash script due to at executes commands using /bin/sh but I'm not sure.
Please tell me if I'm right and I would appreciate some alternative to my code since even it is useless I'm curious to know what's wrong with at and bash.
The #! line only affects what happens when you run a script as a program (e.g. using it as a command in the shell). When you use at, it's not being run as a program, it's simply used as the standard input to /bin/sh, so the shebang has no effect.
You could do:
echo './g.sh' | at 18:06
I am looking at a tcsh script that has the following shebang line:
#!/bin/tcsh -fb
# then executes some commands
What does the -b do?
From the man page:
-b Forces a ''break'' from option processing, causing any further shell arguments to
be treated as non-option arguments. The remaining arguments will not be inter-
preted as shell options. This may be used to pass options to a shell script with-
out confusion or possible subterfuge. The shell will not run a set-user ID script
without this option.
But I don't really understand what it means...
An example would be great.
Thanks.
Say, for example, you have a script that is named --help and you want to execute it using tcsh:
tcsh --help
This will obviously not work. The -b forces tcsh to stop looking for arguments and treat the rest of the command line as file names or arguments to scripts. So, to run the above weirdly named script, you could do
tcsh -b --help