I'm trying to create a BASH script that takes data from four different text files and assigns each line from each of the text files to a variable and then run a command using those variables. I already have a for loop constructed to do this task but the challenge I'm having is the for loop isn't doing one on one mapping.
I want this loop to iterate thru every line and run the command once per line and stop the loop when it reaches the EOF. When I run this script, I get the output as follows;
The username is jsmith The hostname is 0000-Ubuntu The description is P-Ubuntu The IP is 0.0.0.0/24
The username is jsmith The hostname is 0000-Ubuntu The description is P-Ubuntu The IP is 1.1.1.1/24
The username is jsmith The hostname is 0000-Ubuntu The description is P-Ubuntu The IP is 2.2.2.2/24
I need this to be one one one mapped; for example:
The username is jsmith The hostname is 0000-Ubuntu The description is P-Ubuntu The IP is 0.0.0.0/24
The username is pstone The hostname is 1111-Ubuntu The description is P-Ubuntu The IP is 1.1.1.1/24
The username is drogers The hostname is 3333-Ubuntu The description is P-Ubuntu The IP is 3.3.3.3/24
and so on....
As you can tell, I'm a newbie in bash scripting and I'd really appreciate any guidance/help.
Thanks!
#!/bin/bash
HOSTNAMES=$(cat /home/squadri/hostnames.txt)
DESCRIPTIONS=$(cat /home/squadri/descriptions.txt)
USERNAMES=$(cat /home/squadri/usernames.txt)
IPS=$(cat /home/squadri/ips.txt)
for i in $HOSTNAMES ; do
for j in $DESCRIPTIONS ; do
for k in $USERNAMES ; do
for l in $IPS ; do
echo "The username is $k"
echo "The hostname is $i"
echo "The description is $j"
echo "The IP is $l"
done
done
done
done
You can use the paste command for that:
paste /home/squadri/{hostnames,descriptions,usernames,ips}.txt |\
while read hostname description username ip; do
echo "The username is $username"
echo "The hostname is $hostname"
echo "The description is $description"
echo "The IP is $ip"
done
One potential pitfall with this approach is whitespace characters in your files but it should work fine if there are none in any of the lines in your files.
Read from 4 different file descriptors:
while IFS= read -r hostname;
IFS= read -r description <&3;
IFS= read -r username <&4;
IFS= read -r ip <&5; do
echo "The username is $username"
echo "The hostname is $hostname"
echo "The description is $description"
echo "The IP is $ip"
done < hostnames.txt 3< descriptions.txt 4< usernames.txt 5< ips.txt
Technically, this reads until the end of descriptions.txt, regardless of the length of the other files. To stop when the shortest file ends, join the commands with &&:
while IFS= read -r hostname &&
IFS= read -r description <&3 &&
IFS= read -r username <&4 &&
IFS= read -r ip <&5; do
echo "The username is $username"
echo "The hostname is $hostname"
echo "The description is $description"
echo "The IP is $ip"
done < hostnames.txt 3< descriptions.txt 4< usernames.txt 5< ips.txt
Iterating until you reach the end of the longest file is a little more complex (you can't simply join the commands with ||), so I'll leave it as an exercise to the interested reader unless requested.
Related
The main issue I am having with this is pinging the read in IP address. It always says that the address is down.
Ping_Sweep()
{
echo -e '\n'
echo '----- Ping Sweep -----'
echo -e '\n'
command date >> pingresults.tx
echo "Enter in the first three number sequences of an IP address (ex. ###.###.###): "
read -r ip_address
for x in $ip_address
do
echo "IP address being pinged: $ip_address"
if ping –c 1 "$x" &> /dev/null
then
echo "IP: $x is up."
else
echo "Ping failed. $x is down."
fi
done
Main_Menu
}
ping –c should be ping -c. Your original command has an en dash. This is usually caused by copying code rendered by a bad blog framework.
I need a help, i need line brake in my "eval echo".
It is a code for adding multiple additional ip in my server.
code:
#!/bin/bash
echo enter all ip
vi textfile.txt
echo gateway
read g
echo netmask
read n
echo how many ip do you need
read t
for ((u=1;; u++));
do
read "d$u" || break;
done < textfile.txt
for i in `eval echo {1..$t}`
do
eval "echo DEVICE=eth0:$i\nIPADDR=\$d$i\nNETMASK=$n\nGATEWAY=$g\n" # > "ifcfg-eth0:$i";
done
output:
DEVICE=eth0:1nIPADDR=192.168.0.2nNETMASK=255.255.255.0nGATEWAY=192.168.0.1n
required output:
DEVICE=eth0:1
IPADDR=192.168.0.2
NETMASK=255.255.255.0
GATEWAY=192.168.0.1
I have this code:
#!/bin/bash
for some_host in $(cat some_list); do
echo $some_host
ssh $some_host sudo cat /etc/some.conf |grep -i something_to_grep
printf "\nPut the input: " read some_input
echo $some_input
done
When I run it, it just continues without waiting for my input. I need to copy/past something form ssh output for further action :/
Change
printf "\nPut the input: " read some_input
to
read -p "Put the input: " some_input
Example
for host in '1.1.1.100' '1.1.1.101' '1.1.1.102'
do
read -p "Enter your input for ${host} " host_input
echo "${host} says ${host_input}"
done
if [ "$1" == "-s" ]; then
echo "Connecting to host.."
scp root#IP_ADDRESS:/private/var/mobile/Library/SMS/sms.db /private/var/mobile/Media/BackupSMS
echo " "
exit
fi
I need to ask user for a IP-address, that will then be placed where IP_ADDRESS is above. I'm new to scripts, but I'm trying.
How would I do this?
Use the built in read command
read IP_ADDRESS
or, if you want a nice prompt:
read -p "Enter ip address: " IP_ADDRESS
and then add a $ to the scp line:
scp root#$IP_ADDRESS:/...
^
My problem is to add a username to a file, I really stuck to proceed, please help.
Problem: I am having a file called usrgrp.dat. The format of this file is like:
ADMIN:srikanth,admin
DEV:dev1
TEST:test1
I am trying to write a shell script which should give me the output like:
Enter group name: DEV
Enter the username: dev2
My expected output is:
User added to Group DEV
If I see the contents of usrgrp.dat, it should now look like:
DEV:dev1,dev2
TEST:test1
And it should give me error saying user already present if I am trying to add already existing user in that group. I am trying this out with the following script:
#!/bin/sh
dispgrp()
{
groupf="/home/srikanth/scm/auths/group.dat"
for gname in `cat $groupf | cut -f1 -d:`
do
echo $gname
done
echo "Enter the group name:"
read grname
for gname in `cat $groupf | cut -f1 -d:`
do
if [ "$grname" = "$gname" ]
then
echo "Enter the username to be added"
read uname
for grname in `cat $groupf`
do
$gname="$gname:$uname"
exit 1
done
fi
done
}
echo "Group display"
dispgrp
I am stuck and need your valuable help.
#!/bin/sh
dispgrp()
{
groupf="/home/srikanth/scm/auths/group.dat"
tmpfile="/path/to/tmpfile"
# you may want to pipe this to more or less if the list may be long
cat "$groupf" | cut -f1 -d:
echo "Enter the group name:"
read grname
if grep "$grname" "$groupf" >/dev/null 2>&1
then
echo "Enter the username to be added"
read uname
if ! grep "^$grname:.*\<$uname\>" "$groupf" >/dev/null 2>&1
then
sed "/^$grname:/s/\$/,$uname/" "$groupf" > "$tmpfile" && mv "$tmpfile" "$groupf"
else
echo "User $uname already exists in group $grname"
return 1
fi
else
echo "Group not found"
return 1
fi
}
echo "Group display"
dispgrp
You don't need to use loops when the loops are done for you (e.g. cat, sed and grep).
Don't use for to iterate over the output of cat.
Don't use exit to return from a function. Use return.
A non-zero exit or return code signifies an error or failure. Use 0 for normal, successful return. This is the implicit action if you don't specify one.
Learn to use sed and grep.
Since your shebang says #!/bin/sh, the changes I made above are based on the Bourne shell and assume POSIX utilities (not GNU versions).
Something like (assume your shell is bash):
adduser() {
local grp="$1"
local user="$2"
local gfile="$3"
if ! grep -q "^$grp:" "$gfile"; then
echo "no such group: $grp"
return 1
fi
if grep -q "^$grp:.*\\<$user\\>" "$gfile"; then
echo "User $user already in group $grp"
else
sed -i "/^$grp:/s/\$/,$user/" "$gfile"
echo "User $user added to group $grp"
fi
}
read -p "Enter the group name: " grp
read -p "Enter the username to be added: " user
adduser "$grp" "$user" /home/srikanth/scm/auths/group.dat