How can I exclude all “permission denied” result lines from “grep”? - linux

So, the thing is, I'm on linux terminal using grep command and I want the output without all the lines where it prints at the beginning "grep:" or the lines that begins with "./", because now I'm getting something like this:
grep: ./users/blabla1: Permission denied
grep: ./users/blabla2: Permission denied
grep: ./users/blabla3: Permission denied
grep: ./users/blabla4: Permission denied
grep: ./users/blabla5: Permission denied
grep: ./users/blabla6: Permission denied
grep: ./users/blabla7: Permission denied
grep: ./users/blabla8: Permission denied
./foo/bar/log.log
./foo/bar/xml.xml
I have tried this:
grep -irl "foo" . | grep -v "Permission denied"
I have also tried this one:
grep -irl "foo" . | grep -v "^grep:"
And finally this one:
grep -irl "foo" . | grep "^./"
But I keep getting same results as if I haven't put anything after the |, any ideas? What am I missing?

The messages you are receiving is due to a lack of permission on those files, i.e., those are error messages.
All you have to do is to redirect the stderr (standard error output) to /dev/null, like this:
grep -irl "foo" 2> /dev/null
To lear more about redirection (on bash), read this article:
Bash Reference Manual - Redirections
Edit: You can also just suppress error messages by using:
grep -irl "foo" 2>&-

I prefer to use the -s 'suppress' flag:
grep -irls "foo"
Note the "Portability note" from the grep man page:
-s, --no-messages
Suppress error messages about nonexistent or unreadable files. Portability note: unlike GNU grep, 7th Edition Unix grep did not conform to POSIX, because it lacked -q and its -s option behaved like GNU grep's -q option. USG-style grep also lacked -q but its -s option behaved like GNU grep. Portable shell scripts should avoid both -q and -s and should redirect standard and error output to /dev/null instead. (-s is specified by POSIX.)

Going off of your first try:
grep -irl "foo" . | grep -v "Permission denied"
You're just missing the operator to redirect standard error. '|' redirects standard output. if you add '&', you will also redirect standard error, which is what is giving you the "Permission denied" message. Try:
grep -irl "foo" . &| grep -v "Permission denied"
This works for me, because for some reason my machine doesn't like the "2> /dev/null" option.

Related

Difference between shell command `ls –z >output.txt` and `ls –z 2>output.txt`?

I'm trying to learn shell commands. I know ls >output.txt saves the output to output.txt. However, what exactly does ls -z >output.txt do? In my book, it says it does Not save the output to output.txt. If this is true, where Does it save / print it? Also, is -z what causes it to not save it?
Lastly, what does ls -z 2>output.txt do? I know 2 refers to stderr (so the standard error). Does this mean it saves the error (if any) of ls in output.txt? If yes, where does the stdout get printed / saved? And what does the -z mean in this case?
Thanks in advance!
There is no option -z for ls on Linux. So let's see what happens:
$ LANG=C ls -z > /tmp/x
ls: invalid option -- 'z'
Try 'ls --help' for more information.
The error message goes to STDERR which is connected to the terminal.
The standard output (which is empty) is redirected to /tmp/x so we get an empty file.
$ LANG=C ls -z 2> /tmp/x
In this second scenario STDOUT is connected to the terminal, however there is no output. The error message which got sent to STDERR lands in /tmp/x:
$ cat /tmp/x
ls: invalid option -- 'z'
Try 'ls --help' for more information.

grep and tee to identify errors during installation

In order to identify if my installation has errors that I should notice, I am using grep command on the file and write the file using tee because I need to elevate permissions.
sudo grep -inw ${LOGFOLDER}/$1.log -e "failed" | sudo tee -a ${LOGFOLDER}/$1.errors.log
sudo grep -inw ${LOGFOLDER}/$1.log -e "error" | sudo tee -a ${LOGFOLDER}/$1.errors.log
The thing is that the file is created even if the grep didn't find anything.
Is there any way I can create the file only if the grep found a match ?
Thanks
You may replace tee with awk, it won't create file if there is nothing to write to it:
... | sudo awk "{print; print \$0 >> \"errors.log\";}"
But such feature of awk is rarely used. I'd rather remove empty error file if nothing is found:
test -s error.log || rm -f error.log
And, by the way, you may grep for multiple words simultaneously:
grep -E 'failed|error' ...

How can I suppress error messages of a command?

How can I suppress error messages for a shell command?
For example, if there are only jpg files in a directory, running ls *.zip gives an error message:
$ ls *.zip
ls: cannot access '*.zip': No such file or directory
Is there an option to suppress such error messages? I want to use this command in a Bash script, but I want to hide all errors.
Most Unix commands, including ls, will write regular output to standard output and error messages to standard error, so you can use Bash redirection to throw away the error messages while leaving the regular output in place:
ls *.zip 2> /dev/null
$ ls *.zip 2>/dev/null
will redirect any error messages on stderr to /dev/null (i.e. you won't see them)
Note the return value (given by $?) will still reflect that an error occurred.
To suppress error messages and also return the exit status zero, append || true. For example:
$ ls *.zip && echo hello
ls: cannot access *.zip: No such file or directory
$ ls *.zip 2>/dev/null && echo hello
$ ls *.zip 2>/dev/null || true && echo hello
hello
$ touch x.zip
$ ls *.zip 2>/dev/null || true && echo hello
x.zip
hello
I attempted ls -R [existing file] and got an immediate error.
ls: cannot access 'existing file': No such file or directory
So, I used the following:
ls -R 2>dev/null | grep -i [existing file]*
ls -R 2>dev/null | grep -i text*
Or, in your case:
ls -R 2>dev/null | grep -i *.zip
My solution with a raspberry pi3 with buster.
ls -R 2>/dev/null | grep -i [existing file]*
2>/dev/null is very usefull with Bash script to avoid useless warnings or errors.
Do not forget slash caracter

'Permission Denied' even while running as root

I have a simple bash shell script:
user_exists=cat /etc/passwd | grep 'GNU Mailman'
echo $user_exists
when I run this script with sudo ./'script_name', I get a permission denied error on the line where I attempt to access /etc/passwd. What am I doing wrong here?
To understand why, you have to look at the line the way that bash looks at the line:
user_exists=cat /etc/passwd | grep 'GNU Mailman'
According to bash, you are (temporarily) setting the environment variable user_exists to have the value cat. With that value set, then the program /etc/passwd is executed and its output sent to grep 'GNU Mailman'. Since /etc/passwd does not have execute permission, this command fails for lack of permission.
The solution is to use the proper format for process substitution as outlined by Vladimir Kolesnikov:
user_exist=$(grep 'GNU Mailman' /etc/passwd)
user_exists=$(cat /etc/passwd | grep 'GNU Mailman')
or better yet,
getent passwd username

scp output as logfile

I am relatively new to using scp - and I am trying to do some simple stuff over ec2 - something like the following:
scp -i ec2key.pem username#ec2ip:/path/to/file ~/path/to/dest/folder/file
What I would like to have is the log of the above command (i.e the screen output to a text file) - Is there a way to achieve this?
Thanks.
You can redirect both outputs (stdout, stderr) of the command with &> provided you use the verbose (-v) argument. Otherwise, scp will suppress the output as it expects its stdout to be connected to a terminal. But then you get too much information, which you can get rid of with grep:
scp -v -i ec2key.pem username#ec2ip:/path/to/file ~/path/to/dest/folder/file |& grep -v ^debug > file.log
If you want to have the output both to the screen and the file, use tee
scp -v -i ec2key.pem username#ec2ip:/path/to/file ~/path/to/dest/folder/file |& grep -v ^ debug tee file.log
scp -v -i ec2key.pem username#ec2ip:/p/t/file ~/p/t/d/f/file >> something.log 2>&1
-v and 2>&1 will append your extended details (i.e. debug info) in the existing something.log file.
How about (untested, compressing /path/to for readability):
(scp -i ec2key.pem username#ec2ip:/p/t/file ~/p/t/d/f/file ) 2>/p/t/textfile

Resources