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
Related
I'm experimenting with some arguments for the rename command by using -n option to do "dry runs". How to make it output into a file so I can analyze more? The following does not work -- the resultant rename.log is empty:
bash$ echo "XXX" > \"XXX\"__XXX.txt
$ rename -n 's/"([^\/"《》]+)"__(.*)/“$1”__$2/' '{}' \; *.txt > rename.log
'"XXX"__XXX.txt' would be renamed to '“XXX”__XXX.txt'
Mark's comment is correct, it seems the -n option outputs on stderr. So you can run a command like this:
rename -n [options] > rename.log 2>&1
If you wanted to pipe the output to another command (as I was trying to do), put the redirection before the pipe:
rename -n [options] 2>&1 | less
How do you use a command line argument as a file path and check for file existence in Bash?
I have the simple Bash script test.sh:
#!/bin/bash
set -e
echo "arg1=$1"
if [ ! -f "$1" ]
then
echo "File $1 does not exist."
exit 1
fi
echo "File exists!"
and in the same directory, I have a data folder containing stuff.txt.
If I run ./test.sh data/stuff.txt I see the expected output:
arg1=data/stuff.txt
"File exists!"
However, if I call this script from a second script test2.sh, in the same directory, like:
#!/bin/bash
fn="data/stuff.txt"
./test.sh $fn
I get the mangled output:
arg1=data/stuff.txt
does not exist
Why does the call work when I run it manually from a terminal, but not when I run it through another Bash script, even though both are receiving the same file path? What am I doing wrong?
Edit: The filename does not have spaces. Both scripts are executable. I'm running this on Ubuntu 18.04.
The filename was getting an extra whitespace character added to it as a result of how I was retrieving it in my second script. I didn't note this in my question, but I was retrieving the filename from folder list over SSH, like:
fn=$(ssh -t "cd /project/; ls -t data | head -n1" | head -n1)
Essentially, I wanted to get the filename of the most recent file in a directory on a remote server. Apparently, head includes the trailing newline character. I fixed it by changing it to:
fn=$(ssh -t "cd /project/; ls -t data | head -n1" | head -n1 | tr -d '\n' | tr -d '\r')
Thanks to #bigdataolddriver for hinting at the problem likely being an extra character.
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
I am trying to assign the output of mkdir command to a variable. So I can use the directory further.
-bash-4.1$ pwd
/user/ravi/myscripts/tmpdata
-bash-4.1$ OUTPUT=$(mkdir tmpbkp.`date +%F`)
-bash-4.1$ ls | grep tmp
tmpbkp.2017-04-06
-bash-4.1$ echo "$OUTPUT"
But the directory name is not assigning to the variable. Could you please correct me where I am wrong.
When you run the mkdir command by itself, look how much output it produces:
$ mkdir foo
$
None!
When you use a command substitution to generate the argument to mkdir, look how much extra output you get:
$ mkdir tmpbkp.`date +%F`
$
None!
When you put it inside $() it still produces no output.
There is a -v option for mkdir (in the GNU version at least) which produces some output, but it's probably not what you want.
You want the name of the directory in a variable? Put it in a variable first, then call mkdir.
$ thedir=tmpbkp.`date +%F`
$ mkdir $thedir
$ echo $thedir
tmpbkp.2017-04-06
$
I'm trying to echo the new directory that I'm creating in the script.
BACKUP_DIR=`mkdir /tmp/"$TICKET_NUM"_EAR_BACKUP_"$(date "+%Y%m%d")"`
echo $BACKUP_DIR
But, the newly created directory is echoed in the screen. Anything Im missing here?
mkdir -v seems to print out the created directory, whereas mkdir is completely silent on my systems (tested on Mac OS X and Ubuntu Linux). However, you still need to parse out the directory name from this output:
mkdir /tmp/foo
(no output)
mkdir -v /tmp/foo
mkdir: created directory `/tmp/foo'
DIR=$(mkdir -v /tmp/foo | cut -d\ -f4- | tr -d "'\`")
echo $DIR
/tmp/foo
So in your case:
BACKUP_DIR=$( mkdir /tmp/"$TICKET_NUM"_EAR_BACKUP_"$(date "+%Y%m%d")" | cut -d\ -f4- | tr -d "'\`" )
You might want to use the -p switch in order to create the full directory hierarchy. (Yes, /tmp will exist on MOST machines, but sometimes things can really be screwed up...).
var=`cmd` catches output of cmd and stores in $var. But mkdir outputs nothing on success, so $BACKUP_DIR is empty.
BACKUP_DIR="/tmp/"$TICKET_NUM"_EAR_BACKUP_"$(date "+%Y%m%d")
mkdir $BACKUP_DIR
echo $BACKUP_DIR
This should work.