Im trying to do a shell script to add and delete users to a text file.
I want to use the args to compare if delete or add user, but no matter what args I put, both codes run, this is my code:
#!/bin/bash
arg1="$1"
arg2="$2"
if [ "$arg1"="add" ]; then
if ! grep -q $arg2 "users.txt"; then
sed -i -e 's/users:/users: \n - '$arg2'/g' users.txt
echo "user added: $arg2"
else
echo "user exists: $arg2"
fi
fi
if [ "$arg1"="del" ]; then
if grep -q $arg2 "users.txt"; then
sed -i -e 's/- '$arg2'//g' users.txt
echo "user $arg2 deleted"
else
echo "not found $arg2"
fi
fi
This is my text file users.txt:
users:
- angel
- rick
Running sh addUser.sh add user1 on terminal:
user added: user1
user user1 deleted
Running sh addUser.sh del user1 on terminal:
user added: user1
user user1 deleted
The result is the same, how can I fix it?
Thanks to #melpomene for the advice
The problem was the spaces in [ "$arg1"="add" ]
Change [ "$arg1"="add" ] to [ "$arg1" = "add" ] and it works perfectly.
#!/bin/bash
arg1="$1"
arg2="$2"
if [ "$arg1" = "add" ]; then
if ! grep -q $arg2 "users.txt"; then
sed -i -e 's/users:/users: \n - '$arg2'/g' users.txt
echo "user added: $arg2"
else
echo "user exists: $arg2"
fi
fi
if [ "$arg1" = "del" ]; then
if grep -q $arg2 "users.txt"; then
sed -i -e 's/- '$arg2'//g' users.txt
echo "user $arg2 deleted"
else
echo "not found $arg2"
fi
fi
Related
I have many javascript files in my solaris server which have some debug, print and trace statements which I want to comment. There are hundreds of file like this.
I have found a script to do this but the problem is the script is removing the urhk_b2k_printRepos statement instead of commenting it. The script is as below:
if [ $# -ne 2 ]
then
echo "usage: prdel <script file name> <directory in which scripts are present>"
exit 1
fi
file=$1
dir=$2
if [ ! -s ${file} ]
then
echo "script file ${file} either does not exist or is empty (zero bytes)"
echo "Exiting..."
exit 1
fi
if [ ! -d ${dir} ]
then
echo "Invalid directory ${dir} entered"
echo "Exiting..."
exit 1
fi
cordir="./corrected"
prlogdir="./prlog"
if [ -d ${cordir} ]
then
echo "The corrected directory exist in the path, Please remove and run the tool again"
echo "Exiting..."
exit 1
else
mkdir ${cordir}
fi
if [ -d ${prlogdir} ]
then
echo "The prlog directory exist in the path, Please remove and run the tool again"
echo "Exiting..."
exit 1
else
mkdir ${prlogdir}
fi
errFile="$prlogdir/scr_err.rpt"
sucFile="$prlogdir/scr_suc.rpt"
Lines=`wc -l $file`
cntr=1
while [ $cntr -le $Lines ]
do
src=`head -$cntr $file|tail -1`
echo "$cntr. Processing $src...."
srcPath="${dir}/${src}"
if [ ! -s ${srcPath} ]
then
echo "Script file ${src} does not exist in the path given" >> ${errFile}
else
cp $srcPath $cordir/$src.tmp
srctemp="$cordir/$src.tmp"
srccor="$cordir/$src.corrected"
printcnt=`grep -ci "^[ ]*print" $srctemp`
if [ $printcnt -ne 0 ]
then
cat $srctemp|sed 's/^[ ]*[ ]*print[ ]*(/#print(/'|sed 's/^[ ]*[ ]*PRINT[ ]*(/#PRINT(/' > $srccor
mv $srccor $srctemp
fi
prreposcnt=`grep -ci "printrepos" $srctemp`
if [ $prreposcnt -ne 0 ]
then
cat $srctemp|sed 's/^.*urhk_b2k_printRepos.*/#Printrepos statement removed/'|sed 's/^.*urhk_B2k_PrintRepos.*/#Printrepos statement removed/'|sed 's/^.*urhk_B2k_printRepos.*/#Printrepos statement removed/'|sed 's/^.*urhk_b2k_PrintRepos.*/#Printrepos statement removed/' > $srccor
else
cp $srctemp $srccor
fi
echo "Script file $src correction is done" >> ${sucFile}
rm $srctemp
diff $srcPath $srccor >> $prlogdir/$src.diff.rpt
fi
cntr=`expr $cntr + 1`
done
echo "done"
I am completely new to shell scripting. Can anyone help me to modify this script to comment "urhk_b2k_printRepos" lines and also comment "TRACE ON" lines.
The other script is just read statement that will be echo'ed into a file from this script
#!/usr/bin/bash
# createdb_wrapper.scr
# Log information about user of createdb.scr
Default_Dir=/export/home/cwatts/test
Default_Log=DB.Audit
while [ -z "${fname}" ]
do
echo "Please, enter your Fullname [ENTER]:"
read fname
done
Tried various ways to pull the information from the other script
dbname="./createDB.scr | awk '{print $1}'"
sh $dbname
while [ -z "${desc}" ]
do
echo "Please,enter a brief Description [ENTER]:
read desc
done
#Checks the directory exists, and creates if not
if [ ! -d $Default_Dir ] ;then
echo "directory doesn't exit, it will be created"
mkdir $Default_Dir
fi
echo `date -u` '|' $dbname '|' $fname '|' $desc >> $Default_Dir/$Default_Log
exit
You forgot the other quote:
echo "Please,enter a brief Description [ENTER]:
Should be
echo "Please,enter a brief Description [ENTER]:"
I also recommend this form:
#!/bin/bash
#
# createdb_wrapper.scr
# Log information about user of createdb.scr
#
DEFAULT_DIR='/export/home/cwatts/test'
DEFAULT_LOG='DB.Audit'
until read -p "Please, enter your Fullname [ENTER]: " FNAME && [[ -n $FNAME ]]; do
:
done
until read -p "Please,enter a brief Description [ENTER]: " DESC && [[ -n $DESC ]]; do
:
done
if [[ -d $DEFAULT_DIR ]]; then
echo "Directory does not exist. It will be created."
mkdir "$DEFAULT_DIR"
fi
echo "$(exec date -u) | $DBNAME | $FNAME | $DESC" >> "$DEFAULT_DIR/$DEFAULT_LOG"
Note: $DBNAME is not set.
I want to create a script to check whether a user exists. I am using the logic below:
# getent passwd test > /dev/null 2&>1
# echo $?
0
# getent passwd test1 > /dev/null 2&>1
# echo $?
2
So if the user exists, then we have success, else the user does not exist. I have put above command in the bash script as below:
#!/bin/bash
getent passwd $1 > /dev/null 2&>1
if [ $? -eq 0 ]; then
echo "yes the user exists"
else
echo "No, the user does not exist"
fi
Now, my script always says that the user exists no matter what:
# sh passwd.sh test
yes the user exists
# sh passwd.sh test1
yes the user exists
# sh passwd.sh test2
yes the user exists
Why does the above condition always evaluate to be TRUE and say that the user exists?
Where am I going wrong?
UPDATE:
After reading all the responses, I found the problem in my script. The problem was the way I was redirecting getent output. So I removed all the redirection stuff and made the getent line look like this:
getent passwd $user > /dev/null
Now my script is working fine.
You can also check user by id command.
id -u name gives you the id of that user.
if the user doesn't exist, you got command return value ($?)1
And as other answers pointed out: if all you want is just to check if the user exists, use if with id directly, as if already checks for the exit code. There's no need to fiddle with strings, [, $? or $():
if id "$1" &>/dev/null; then
echo 'user found'
else
echo 'user not found'
fi
(no need to use -u as you're discarding the output anyway)
Also, if you turn this snippet into a function or script, I suggest you also set your exit code appropriately:
#!/bin/bash
user_exists(){ id "$1" &>/dev/null; } # silent, it just sets the exit code
if user_exists "$1"; code=$?; then # use the function, save the code
echo 'user found'
else
echo 'user not found' >&2 # error messages should go to stderr
fi
exit $code # set the exit code, ultimately the same set by `id`
There's no need to check the exit code explicitly. Try
if getent passwd $1 > /dev/null 2>&1; then
echo "yes the user exists"
else
echo "No, the user does not exist"
fi
If that doesn't work, there is something wrong with your getent, or you have more users defined than you think.
Why don't you simply use
grep -c '^username:' /etc/passwd
It will return 1 (since a user has max. 1 entry) if the user exists and 0 if it doesn't.
This is what I ended up doing in a Freeswitch bash startup script:
# Check if user exists
if ! id -u $FS_USER > /dev/null 2>&1; then
echo "The user does not exist; execute below commands to crate and try again:"
echo " root#sh1:~# adduser --home /usr/local/freeswitch/ --shell /bin/false --no-create-home --ingroup daemon --disabled-password --disabled-login $FS_USER"
echo " ..."
echo " root#sh1:~# chown freeswitch:daemon /usr/local/freeswitch/ -R"
exit 1
fi
By far the simplest solution:
if id -u "$user" >/dev/null 2>&1; then
echo 'user exists'
else
echo 'user missing'
fi
The >/dev/null 2>&1 can be shortened to &>/dev/null in Bash, and if you only want to know if a user does not exist:
if ! id -u "$user" >/dev/null 2>&1; then
echo 'user missing'
fi
I suggest to use id command as it tests valid user existence wrt passwd file entry which is not necessary means the same:
if [ `id -u $USER_TO_CHECK 2>/dev/null || echo -1` -ge 0 ]; then
echo FOUND
fi
Note: 0 is root uid.
I was using it in that way:
if [ $(getent passwd $user) ] ; then
echo user $user exists
else
echo user $user doesn\'t exists
fi
Script to Check whether Linux user exists or not
Script To check whether the user exists or not
#! /bin/bash
USER_NAME=bakul
cat /etc/passwd | grep ${USER_NAME} >/dev/null 2>&1
if [ $? -eq 0 ] ; then
echo "User Exists"
else
echo "User Not Found"
fi
Late answer but finger also shows more information on user
sudo apt-get finger
finger "$username"
Using sed:
username="alice"
if [ `sed -n "/^$username/p" /etc/passwd` ]
then
echo "User [$username] already exists"
else
echo "User [$username] doesn't exist"
fi
Actually I cannot reproduce the problem. The script as written in the question works fine, except for the case where $1 is empty.
However, there is a problem in the script related to redirection of stderr. Although the two forms &> and >& exist, in your case you want to use >&. You already redirected stdout, that's why the form &> does not work. You can easily verify it this way:
getent /etc/passwd username >/dev/null 2&>1
ls
You will see a file named 1 in the current directory. You want to use 2>&1 instead, or use this:
getent /etc/passwd username &>/dev/null
This also redirects stdout and stderr to /dev/null.
Warning Redirecting stderr to /dev/null might not be such a good idea. When things go wrong, you will have no clue why.
user infomation is stored in /etc/passwd, so you can use "grep 'usename' /etc/passwd" to check if the username exist.
meanwhile you can use "id" shell command, it will print the user id and group id, if the user does not exist, it will print "no such user" message.
Depending on your shell implementation (e.g. Busybox vs. grown-up) the [ operator might start a process, changing $?.
Try
getent passwd $1 > /dev/null 2&>1
RES=$?
if [ $RES -eq 0 ]; then
echo "yes the user exists"
else
echo "No, the user does not exist"
fi
Login to the server.
grep "username" /etc/passwd
This will display the user details if present.
Below is the script to check the OS distribution and create User if not exists and do nothing if user exists.
#!/bin/bash
# Detecting OS Ditribution
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$NAME
elif type lsb_release >/dev/null 2>&1; then
OS=$(lsb_release -si)
elif [ -f /etc/lsb-release ]; then
. /etc/lsb-release
OS=$DISTRIB_ID
else
OS=$(uname -s)
fi
echo "$OS"
user=$(cat /etc/passwd | egrep -e ansible | awk -F ":" '{ print $1}')
#Adding User based on The OS Distribution
if [[ $OS = *"Red Hat"* ]] || [[ $OS = *"Amazon Linux"* ]] || [[ $OS = *"CentOS"*
]] && [[ "$user" != "ansible" ]];then
sudo useradd ansible
elif [ "$OS" = Ubuntu ] && [ "$user" != "ansible" ]; then
sudo adduser --disabled-password --gecos "" ansible
else
echo "$user is already exist on $OS"
exit
fi
Create system user some_user if it doesn't exist
if [[ $(getent passwd some_user) = "" ]]; then
sudo adduser --no-create-home --force-badname --disabled-login --disabled-password --system some_user
fi
I like this nice one line solution
getent passwd username > /dev/null 2&>1 && echo yes || echo no
and in script:
#!/bin/bash
if [ "$1" != "" ]; then
getent passwd $1 > /dev/null 2&>1 && (echo yes; exit 0) || (echo no; exit 2)
else
echo "missing username"
exit -1
fi
use:
[mrfish#yoda ~]$ ./u_exists.sh root
yes
[mrfish#yoda ~]$ echo $?
0
[mrfish#yoda ~]$ ./u_exists.sh
missing username
[mrfish#yoda ~]$ echo $?
255
[mrfish#yoda ~]$ ./u_exists.sh aaa
no
[mrfish#indegy ~]$ echo $?
2
echo "$PASSWORD" | su -c "cd /" "$USER"
if [ "$?" = "0" ];then
echo "OK"
else
echo "Error"
fi
#!/bin/bash
read -p "Enter your Login Name: " loginname
home=`grep -w $loginname /etc/passwd | cut -ef:6 -d:`
if [ $home ]
echo "Exists"
else
echo "Not Exist"
fi
I'm trying to write an extremely simple script in Ubuntu which would allow me to pass it either a filename or a directory, and be able to do something specific when it's a file, and something else when it's a directory. The problem I'm having is when the directory name, or probably files too, has spaces or other escapable characters are in the name.
Here's my basic code down below, and a couple tests.
#!/bin/bash
PASSED=$1
if [ -d "${PASSED}" ] ; then
echo "$PASSED is a directory";
else
if [ -f "${PASSED}" ]; then
echo "${PASSED} is a file";
else
echo "${PASSED} is not valid";
exit 1
fi
fi
And here's the output:
andy#server~ $ ./scripts/testmove.sh /home/andy/
/home/andy/ is a directory
andy#server~ $ ./scripts/testmove.sh /home/andy/blah.txt
/home/andy/blah.txt is a file
andy#server~ $ ./scripts/testmove.sh /home/andy/blah\ with\ a\ space.txt
/home/andy/blah with a space.txt is not valid
andy#server~ $ ./scripts/testmove.sh /home/andy\ with\ a\ space/
/home/andy with a space/ is not valid
All of those paths are valid, and exist.
That should work. I am not sure why it's failing. You're quoting your variables properly. What happens if you use this script with double [[ ]]?
if [[ -d $PASSED ]]; then
echo "$PASSED is a directory"
elif [[ -f $PASSED ]]; then
echo "$PASSED is a file"
else
echo "$PASSED is not valid"
exit 1
fi
Double square brackets is a bash extension to [ ]. It doesn't require variables to be quoted, not even if they contain spaces.
Also worth trying: -e to test if a path exists without testing what type of file it is.
At least write the code without the bushy tree:
#!/bin/bash
PASSED=$1
if [ -d "${PASSED}" ]
then echo "${PASSED} is a directory";
elif [ -f "${PASSED}" ]
then echo "${PASSED} is a file";
else echo "${PASSED} is not valid";
exit 1
fi
When I put that into a file "xx.sh" and create a file "xx sh", and run it, I get:
$ cp /dev/null "xx sh"
$ for file in . xx*; do sh "$file"; done
. is a directory
xx sh is a file
xx.sh is a file
$
Given that you are having problems, you should debug the script by adding:
ls -ld "${PASSED}"
This will show you what ls thinks about the names you pass the script.
Using -f and -d switches on /bin/test:
F_NAME="${1}"
if test -f "${F_NAME}"
then
echo "${F_NAME} is a file"
elif test -d "${F_NAME}"
then
echo "${F_NAME} is a directory"
else
echo "${F_NAME} is not valid"
fi
Using the "file" command may be useful for this:
#!/bin/bash
check_file(){
if [ -z "${1}" ] ;then
echo "Please input something"
return;
fi
f="${1}"
result="$(file $f)"
if [[ $result == *"cannot open"* ]] ;then
echo "NO FILE FOUND ($result) ";
elif [[ $result == *"directory"* ]] ;then
echo "DIRECTORY FOUND ($result) ";
else
echo "FILE FOUND ($result) ";
fi
}
check_file "${1}"
Output examples :
$ ./f.bash login
DIRECTORY FOUND (login: directory)
$ ./f.bash ldasdas
NO FILE FOUND (ldasdas: cannot open `ldasdas' (No such file or directory))
$ ./f.bash evil.php
FILE FOUND (evil.php: PHP script, ASCII text)
FYI: the answers above work but you can use -s to help in weird situations by checking for a valid file first:
#!/bin/bash
check_file(){
local file="${1}"
[[ -s "${file}" ]] || { echo "is not valid"; return; }
[[ -d "${file}" ]] && { echo "is a directory"; return; }
[[ -f "${file}" ]] && { echo "is a file"; return; }
}
check_file ${1}
Using stat
function delete_dir () {
type="$(stat --printf=%F "$1")"
if [ $? -ne 0 ]; then
echo "$1 directory does not exist. Nothing to delete."
elif [ "$type" == "regular file" ]; then
echo "$1 is a file, not a directory."
exit 1
elif [ "$type" == "directory" ]; then
echo "Deleting $1 directory."
rm -r "$1"
fi
}
function delete_file () {
type="$(stat --printf=%F "$1")"
if [ $? -ne 0 ]; then
echo "$1 file does not exist. Nothing to delete."
elif [ "$type" == "directory" ]; then
echo "$1 is a regular file, not a directory."
exit 1
elif [ "$type" == "regular file" ]; then
echo "Deleting $1 regular file."
rm "$1"
fi
}
https://linux.die.net/man/2/stat
https://en.m.wikipedia.org/wiki/Unix_file_types
A more elegant solution
echo "Enter the file name"
read x
if [ -f $x ]
then
echo "This is a regular file"
else
echo "This is a directory"
fi
Answer based on the title:
Check if passed argument is file or directory in Bash
This works also if the provided argument has a trailing slash .e.g. dirname/
die() { echo $* 1>&2; exit 1; }
# This is to remove the the slash at the end: dirName/ -> dirName
fileOrDir=$(basename "$1")
( [ -d "$fileOrDir" ] || [ -f "$fileOrDir" ] ) && die "file or directory $fileOrDir already exists"
Testing:
mkdir mydir
touch myfile
command dirName
# file or directory mydir already exists
command dirName/
# file or directory mydir already exists
command filename
# file or directory myfile already exists
#!/bin/bash
echo "Please Enter a file name :"
read filename
if test -f $filename
then
echo "this is a file"
else
echo "this is not a file"
fi
One liner
touch bob; test -d bob && echo 'dir' || (test -f bob && echo 'file')
result is true (0)(dir) or true (0)(file) or false (1)(neither)
This should work:
#!/bin/bash
echo "Enter your Path:"
read a
if [[ -d $a ]]; then
echo "$a is a Dir"
elif [[ -f $a ]]; then
echo "$a is the File"
else
echo "Invalid path"
fi
I want to check if file2.sh exists and also if a specific word, poet is part of the file. I use grep to create the variable used_var.
#!/bin/ksh
file_name=/home/file2.sh
used_var=`grep "poet" $file_name`
How can I check if used_var has some value?
Instead of storing the output of grep in a variable and then checking whether the variable is empty, you can do this:
if grep -q "poet" $file_name
then
echo "poet was found in $file_name"
fi
============
Here are some commonly used tests:
-d FILE
FILE exists and is a directory
-e FILE
FILE exists
-f FILE
FILE exists and is a regular file
-h FILE
FILE exists and is a symbolic link (same as -L)
-r FILE
FILE exists and is readable
-s FILE
FILE exists and has a size greater than zero
-w FILE
FILE exists and is writable
-x FILE
FILE exists and is executable
-z STRING
the length of STRING is zero
Example:
if [ -e "$file_name" ] && [ ! -z "$used_var" ]
then
echo "$file_name exists and $used_var is not empty"
fi
if test -e "$file_name";then
...
fi
if grep -q "poet" $file_name; then
..
fi
test -e will test whether a file exists or not. The test command returns a zero value if the test succeeds or 1 otherwise.
Test can be written either as test -e or using []
[ -e "$file_name" ] && grep "poet" $file_name
Unless you actually need the output of grep you can test the return value as grep will return 1 if there are no matches and zero if there are any.
In general terms you can test if a string is non-empty using [ "string" ] which will return 0 if non-empty and 1 if empty
If you have the test binary installed or ksh has a matching built-in function, you could use it to perform your checks. Usually /bin/[ is a symbolic link to test:
if [ -e "$file_name" ]; then
echo "File exists"
fi
if [ -z "$used_var" ]; then
echo "Variable is empty"
fi
You should use the grep -q flag for quiet output. See the man pages below:
man grep output :
General Output Control
-q, --quiet, --silent
Quiet; do not write anything to standard output. Exit immediately with zero status
if any match is found, even if an error was detected. Also see the -s or
--no-messages option. (-q is specified by POSIX.)
This KornShell (ksh) script demos the grep quiet output and is a solution to your question.
grepUtil.ksh :
#!/bin/ksh
#Initialize Variables
file=poet.txt
var=""
dir=tempDir
dirPath="/"${dir}"/"
searchString="poet"
#Function to initialize variables
initialize(){
echo "Entering initialize"
echo "Exiting initialize"
}
#Function to create File with Input
#Params: 1}Directory 2}File 3}String to write to FileName
createFileWithInput(){
echo "Entering createFileWithInput"
orgDirectory=${PWD}
cd ${1}
> ${2}
print ${3} >> ${2}
cd ${orgDirectory}
echo "Exiting createFileWithInput"
}
#Function to create File with Input
#Params: 1}directoryName
createDir(){
echo "Entering createDir"
mkdir -p ${1}
echo "Exiting createDir"
}
#Params: 1}FileName
readLine(){
echo "Entering readLine"
file=${1}
while read line
do
#assign last line to var
var="$line"
done <"$file"
echo "Exiting readLine"
}
#Check if file exists
#Params: 1}File
doesFileExit(){
echo "Entering doesFileExit"
orgDirectory=${PWD}
cd ${PWD}${dirPath}
#echo ${PWD}
if [[ -e "${1}" ]]; then
echo "${1} exists"
else
echo "${1} does not exist"
fi
cd ${orgDirectory}
echo "Exiting doesFileExit"
}
#Check if file contains a string quietly
#Params: 1}Directory Path 2}File 3}String to seach for in File
doesFileContainStringQuiet(){
echo "Entering doesFileContainStringQuiet"
orgDirectory=${PWD}
cd ${PWD}${1}
#echo ${PWD}
grep -q ${3} ${2}
if [ ${?} -eq 0 ];then
echo "${3} found in ${2}"
else
echo "${3} not found in ${2}"
fi
cd ${orgDirectory}
echo "Exiting doesFileContainStringQuiet"
}
#Check if file contains a string with output
#Params: 1}Directory Path 2}File 3}String to seach for in File
doesFileContainString(){
echo "Entering doesFileContainString"
orgDirectory=${PWD}
cd ${PWD}${1}
#echo ${PWD}
grep ${3} ${2}
if [ ${?} -eq 0 ];then
echo "${3} found in ${2}"
else
echo "${3} not found in ${2}"
fi
cd ${orgDirectory}
echo "Exiting doesFileContainString"
}
#-----------
#---Main----
#-----------
echo "Starting: ${PWD}/${0} with Input Parameters: {1: ${1} {2: ${2} {3: ${3}"
#initialize #function call#
createDir ${dir} #function call#
createFileWithInput ${dir} ${file} ${searchString} #function call#
doesFileExit ${file} #function call#
if [ ${?} -eq 0 ];then
doesFileContainStringQuiet ${dirPath} ${file} ${searchString} #function call#
doesFileContainString ${dirPath} ${file} ${searchString} #function call#
fi
echo "Exiting: ${PWD}/${0}"
grepUtil.ksh Output :
user#foo /tmp
$ ksh grepUtil.ksh
Starting: /tmp/grepUtil.ksh with Input Parameters: {1: {2: {3:
Entering createDir
Exiting createDir
Entering createFileWithInput
Exiting createFileWithInput
Entering doesFileExit
poet.txt exists
Exiting doesFileExit
Entering doesFileContainStringQuiet
poet found in poet.txt
Exiting doesFileContainStringQuiet
Entering doesFileContainString
poet
poet found in poet.txt
Exiting doesFileContainString
Exiting: /tmp/grepUtil.ksh