- Linux shell script not giving any output
- 2 Answers 2
- No output from script
- 4 Answers 4
- How to silence output in a Bash script?
- 9 Answers 9
- Redirect stderr to stdout
- Redirect stdout to File
- Redirect stderr and stdout to File
- Redirect stderr and stdout to /dev/null
- Useful variations:
- How can I suppress all output from a command using Bash?
- 9 Answers 9
- Why does this script produce no output?
Linux shell script not giving any output
Are your files called cat and list or do you want to read the files from a file called list ? If the last, you should write: for i in $(cat list) or while read i; do . done < list . And there seem to be a few ` characters missing from your script
The program you posted would cause a lot of errors. Please post your real code. Maybe you left out some backticks? (Why on earth would you do that? Copy-paste, it’s easy!)
2 Answers 2
for i in cat list; do echo $i; done
Will just print cat and list as output.
If you just want to run for loop for each line of file list then use:
while read l do echo "$i" # repalce echo with your actual script commands and keep "$i" in double quotes done < list
Also "$i" should be in double quotes except under very specific circumstances which are hardly applicable here.
Assuming you really had backticks where they are needed, and taking Anubhava's correction into account, the major remaining issue is that sed does not treat $c as the value of a shell variable - you need double quotes in this context to make the shell expand the value of the variable before sed sees it.
while read -r i; do a=$(awk '' "$i") b=$(awk '' "$i") c=$(wc -l < "$i") d=$(expr "$c" - 1) e=$(sed -n "$p") f=$(sed -n "$p") printf "$a $b $e $f\n" done >output.txt
Notice also the judicious use of double quotes around variable names, and the refactoring of the output redirection. If you mean to overwrite output.txt instead of appending, use a single > .
This is still not a pretty script, but without knowledge of the actual problem and the desired input and output, it's hard to say how to improve it. By the general looks of it, rewriting it entirely in Awk might be a good idea.
No output from script
I've edited my script, and get no more errors, however, the script is not executing to the Minecraft server, no announcement attempts are made at all for that matter. I'm rally puzzled. It's as if it's not running at all like the server is not running, but it is, and should be matching "is running" from the status command. and code is:
#!/bin/bash checkServer=$(/etc/init.d/minecraft status); cd /.smc; # Is the server even running? if [ checkServer = *"is running"* ]; then # No count file? Create it. if [ ! -f /.smc/lastAnnouncement.txt ]; then echo 0 < /.smc/lastAnnouncement.txt; fi # Load count lastAnn=$(cat /.smc/lastAnnouncement.txt); # ANNOUNCEMENTS announcement[0]='Dont forget to check out http://fb.com/pyrexiacraftfans for news and updates'; announcement[1]='Use our Facebook page to request land protection! Visit http://fb.com/pyrexiacraftfans'; # Should we restart announcement que? if lastAnn == $+1; then echo 0 < /.smc/lastAnnouncement.txt; fi # Send announcement sendAnnouncement=$(/etc/init.d/minecraft command say announcement[lastAnn]); # Next announcement count lastAnn=$((lastAnn+1)); # Write next announacment count echo lastAnn < /.smc/lastAnnouncement.txt; fi
Your script is wrong on so so so many levels, that it is not a shell script. It is not even logical. I'm correcting it and creating an answer.
4 Answers 4
There are multiple issues with your script, ranging from useless semicolons to bad logic. The list of issues is so long that it's easier to post a corrected script than point out the issues (the other answers don't even come close to listing all the errors).
#!/bin/bash checkServer=$(/etc/init.d/minecraft status) cd /.smc # Is the server even running? if [[ $checkServer =~ "is running" ]]; then # No count file? Create it. if [ ! -f /.smc/lastAnnouncement.txt ]; then echo 0 > /.smc/lastAnnouncement.txt fi # Load count lastAnn=$(cat /.smc/lastAnnouncement.txt) # ANNOUNCEMENTS announcement[0]='Dont forget to check out http://fb.com/pyrexiacraftfans for news and updates' announcement[1]='Use our Facebook page to request land protection! Visit http://fb.com/pyrexiacraftfans' # Send announcement sendAnnouncement=$(/etc/init.d/minecraft command say $) # Next announcement count ((++lastAnn)) # Write next announacment count # Should we restart announcement que? if [[ $lastAnn -gt $ ]]; then echo 0 > /.smc/lastAnnouncement.txt else echo $lastAnn > /.smc/lastAnnouncement.txt fi fi
The issues with your script (leaving aside the excess semicolons which don't hurt, just needless disk space wastage):
- missing $ before variable name
- Incorrect string comparison. Use =~ instead of == , [[ instead of [ , and remove * from both sides of the string *"is running"*
if [ checkServer == *"is running"* ]
I won't go into the fact that the logic of writing the message queue index was incorrect, and would never loop back to 0 .
However, you did a wonderful job of trying to write a script. Many people don't even try.
Edit : I missed out a <> on the array variable usage on line 21 of the script above. Fixed.
How to silence output in a Bash script?
I have a program that outputs to stdout and would like to silence that output in a Bash script while piping to a file. For example, running the program will output:
% myprogram % WELCOME TO MY PROGRAM % Done.
#!/bin/bash myprogram > sample.s
From what I recall, redirecting output to a file causes it to not be echoed to the terminal. What's not working for you?
9 Answers 9
If it outputs to stderr as well you'll want to silence that. You can do that by redirecting file descriptor 2:
# Send stdout to out.log, stderr to err.log myprogram > out.log 2> err.log # Send both stdout and stderr to out.log myprogram &> out.log # New bash syntax myprogram > out.log 2>&1 # Older sh syntax # Log output, hide errors. myprogram > out.log 2> /dev/null
The "&>" line is a shorter version of what I just posted. I haven't come across that shortcut before. Upvoting.
git.savannah.gnu.org/cgit/bash.git/tree/CHANGES#n2208 indicates that >>& was introduced in 4.0. There is no mention of &> but the CHANGES only go back to 2.0 so I think that means it was already in 1.x.
git blame on redir.c points to a 1998 commit for the oldest occurrence still in the current code base.
Redirect stderr to stdout
This will redirect the stderr (which is descriptor 2) to the file descriptor 1 which is the the stdout.
Redirect stdout to File
Now when perform this you are redirecting the stdout to the file sample.s
Redirect stderr and stdout to File
Combining the two commands will result in redirecting both stderr and stdout to sample.s
Redirect stderr and stdout to /dev/null
Redirect to /dev/null if you want to completely silent your application.
The last one is missing a redirection operator; it should be myprogram >/dev/null 2>&1 (notice the wedge before /dev/null and the order of the redirections).
scriptname >/dev/null 2>/dev/null
For newer bash (no portable):
This doesn't work. It actually creates a file named - and &> is a non-portable bourne shell extension.
The portable equivalent echo moo 1>&- produces an error because file descriptor 1 is closed: -bash: echo: write error: Bad file descriptor
If you are still struggling to find an answer, specially if you produced a file for the output, and you prefer a clear alternative: echo "hi" | grep "use this hack to hide the oputut 🙂 "
If you want STDOUT and STDERR both [everything], then the simplest way is:
#!/bin/bash myprogram >& sample.s
then run it like ./script , and you will get no output to your terminal. 🙂
the ">&" means STDERR and STDOUT. the & also works the same way with a pipe: ./script |& sed that will send everything to sed
man bash (under "Redirecting Standard Output and Standard Error") says &> and >& are equivalent but the first (&>) is preferred. However |& is the only way to do this for pipes.
Useful variations:
- Get only the STDERR in a file, while hiding any STDOUT even if the program to hide isn't existing at all. (does not ever hang):
stty -echo && ./programMightNotExist 2> errors.log && stty echo
Note: This answer is related to the question "How to turn off echo while executing a shell script Linux" which was in turn marked as duplicated to this one.
To actually turn off the echo the command is:
(this is, for instance; when you want to enter a password and you don't want it to be readable. Remember to turn echo on at the end of your script, otherwise the person that runs your script won't see what he/she types in from then on. To turn echo on run:
How can I suppress all output from a command using Bash?
I have a Bash script that runs a program with parameters. That program outputs some status (doing this, doing that. ). There isn't any option for this program to be quiet. How can I prevent the script from displaying anything? I am looking for something like Windows' "echo off".
9 Answers 9
The following sends standard output to the null device (bit bucket).
And if you also want error messages to be sent there, use one of (the first may not work in all shells):
scriptname &>/dev/null scriptname >/dev/null 2>&1 scriptname >/dev/null 2>/dev/null
And, if you want to record the messages, but not see them, replace /dev/null with an actual file, such as:
For completeness, under Windows cmd.exe (where "nul" is the equivalent of "/dev/null"), it is:
Note that '&>' is peculiar to bash (and maybe C shells); Korn and Bourne shells require 2> /dev/null or 2>&1 (to send stderr to the same place as stdout). The Korn shell seems to interpret '&>' as "run the stuff up to & in background, then do the i/o redirection on an empty command".
Note that some commands write directly to the terminal device rather than to standard output/error. To test, put echo foo > $(tty) in a script and run ./test.sh &> /dev/null - The output is still printed to the terminal. Of course this is not a problem if you're writing a script which uses no such commands.
@l0b0, is there a way to make the script's (or any other program's) tty different so that all output is redirected regardless of your example? I know screen and script can do something like that but both are finicky and vary from *nix to *nix.
This will prevent standard output and error output, redirecting them both to /dev/null .
Even though I'm adding this to my gs (GhostScript) command, it still prints out **** Warning: File has a corrupted %%EOF marker, or garbage after %%EOF. Any advice?
An alternative that may fit in some situations is to assign the result of a command to a variable:
$ DUMMY=$( grep root /etc/passwd 2>&1 ) $ echo $? 0 $ DUMMY=$( grep r00t /etc/passwd 2>&1 ) $ echo $? 1
Since Bash and other POSIX commandline interpreters does not consider variable assignments as a command, the present command's return code is respected.
Note: assignement with the typeset or declare keyword is considered as a command, so the evaluated return code in case is the assignement itself and not the command executed in the sub-shell:
$ declare DUMMY=$( grep r00t /etc/passwd 2>&1 ) $ echo $? 0
Why does this script produce no output?
I'm trying to write a bash script that analyzes the video files in a folder to output the total video duration in that immediate folder and the video duration in that folder plus all its sub-folders. My code is:
#!/bin/bash ### Outputs the total duration of video in each folder (recursively). ## Incase an argument is not provided, the basefolder is assumed to be pwd. # Defining custom Constants & functions RED='\033[1;31m' GREEN='\033[1;32m' YELLOW='\033[1;33m' BLUE='\033[1;34m' NC='\033[0m' # No Color echoErr() < echo -e "$[ERROR]$: $@" 1>&2 exit > folderTime() < echo $(find . -maxdepth 1 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration <>\; | paste -sd+ -| bc) > # Setting the base directory if [ "$#" -lt 1 ]; then baseDir="$(pwd)" else baseDir="$1" fi cd "$baseDir" || echoErr "Error switching to $baseDir" # Actual calculation of the total video duration in each folder - using a function. totalTime=0 function calcTime() < local incomingTime=$totalTime local newTotalTime=0 local immediateTime=0 newTotalTime=immediateTime=$(folderTime) for f in "$1"* do if [ -d "$f" ]; then cd "$f" || echoErr "Can't switch to $f" calcTime "$f" newTotalTime=$(( $newTotalTime + $totalTime )) fi done totalTime=$(( $newTotalTime + $incomingTime )) echo -e "The duration of video in just $f is : \t\t$$immediateTime$" echo -e "The Total duration of video in $f and subfolders is : \t$$totalTime$" > calcTime "$baseDir"
The above code produces no output what so ever, but the neither does the execution halt. I'm pretty sure being new to bash scripting, I've made some kind of error(s), but for the life of me, can't figure out exactly what it is. Please help. Also, please tell me any and all ways of improving this script. Thanks!
Run with bash -x to see where it gets stuck. Also newTotalTime=immediateTime=$(folderTime) won't work the way you think it will.
@muru Please tell me what happens when newTotalTime=immediateTime=$(folderTime) is executed. I'm trying to improvise due to the lack of a true return value in bash.
I'm pretty sure this is just going to cd into . over and over again if that's what you start it on. It should still crash eventually, so if it doesn't halt I'm not sure.