LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   How to read a text file using a bash script (http://www.linuxquestions.org/questions/programming-9/how-to-read-a-text-file-using-a-bash-script-758434/)

Jeroen1000 09-29-2009 07:45 AM

How to read a text file using a bash script
 
Hi everyone,

I know the logic of how I want to do it, but I really don't know how to implement this in bash. I hope someone is willing to help me figure this out.


In a www sub directory of Apache called 'testing', I have made a PHP script that creates a file that has the users' IP-address as its file name. Eg. 192.168.1.239

There is also another file that I've called 'users' that contains following info:

Code:

ip:name:directory
for example:
Code:

192.168.1.239:jeroen:/jeroen/backup
As you can see I've used a : as delimeter.

The bash script should check for files that have an IP-address as their name and match that address with the name that belongs to that ip-address (here is where the 'users' file comes into play).

The best way is that the script creates an array 'arr' which contains:

Code:

arr[0] = 192.168.1.239
arr[1] = jeroen
arr[2] = jeroen/backup

I've done some thinking and I guess I can read the first line of the users file and somehow split it (the array idea above) using the delimeter (that's how I do it in PHP). Then I can use the linux find command to check whether such a file is present in the Apache directory.

I can't figure out how to do these relatively simple operations in bash. I'd be much obliged if you could point this out.

Cheers,

Jeroen

catkin 09-29-2009 07:55 AM

Which way around do you want to do it? Start by looking for "files that have an IP-address as their name" and then look for a corresponding entry in the "users" file, or process the "users" file line by line looking for files with the given IP address? The second is easier but will not find cases of files named by IP address that do not have corresponding entries in the "users" file -- and vice versa, of course.

lutusp 09-29-2009 07:56 AM

Quote:

Originally Posted by Jeroen1000 (Post 3700464)
Hi everyone,

I know the logic of how I want to do it, but I really don't know how to implement this in bash. I hope someone is willing to help me figure this out.


In a www sub directory of Apache called 'testing', I have made a PHP script that creates a file that has the users' IP-address as its file name. Eg. 192.168.1.239

There is also another file that I've called 'users' that contains following info:

Code:

ip:name:directory
for example:
Code:

192.168.1.239:jeroen:/jeroen/backup
As you can see I've used a : as delimeter.

The bash script should check for files that have an IP-address as their name and match that address with the name that belongs to that ip-address (here is where the 'users' file comes into play).

The best way is that the script creates an array 'arr' which contains:

Code:

arr[0] = 192.168.1.239
arr[1] = jeroen
arr[2] = jeroen/backup

I've done some thinking and I guess I can read the first line of the users file and somehow split it (the array idea above) using the delimeter (that's how I do it in PHP). Then I can use the linux find command to check whether such a file is present in the Apache directory.

I can't figure out how to do these relatively simple operations in bash. I'd be much obliged if you could point this out.

Cheers,

Jeroen

Since this sounds like homework, I'll give you some hints but then you're on your own.

1. Get the IPs:

Code:

$ ls -1 (path to location of IP-named files) | while read ip
do
  # process the ip here
done

(the "-1" above is a one digit, not a lowercase 'L')

2. Read a file and filter by user IP:

Code:

user_data=$(grep $ip < user-file)
From here you're on your own.

Jeroen1000 09-29-2009 08:15 AM

Quote:

Originally Posted by catkin (Post 3700476)
Which way around do you want to do it? Start by looking for "files that have an IP-address as their name" and then look for a corresponding entry in the "users" file, or process the "users" file line by line looking for files with the given IP address? The second is easier but will not find cases of files named by IP address that do not have corresponding entries in the "users" file -- and vice versa, of course.

I thought about reading a line of the 'users' file and then executing a

Code:

find /directory_where_ip_files_are/ -name 192.168.1.236
But for that to work I have to be able to split on the : delimeter so the IP address after - name can be replaced by a variable containing the IP in the 'users' file. I would also need to know whether the fnid was successful or not.
So basically, I would process the user's file.

@lutusp, I appreciate the hints:). And nope it's not homework. I've made a PHP page which allows my family to view the size of their backup archive, date when the last backup was made and whether the backup was successful or not. The backup script is running as a cron job: there is a script in every users backup directory with the correct parameters to invoke the script.

Now, I have included a 'backup now' button which drops a file with their IP in the aforementioned folder. The 'users' file is my idea to match things up so that I can invoke the script with the correct parameters.

I knew enough PHP to get this done (I'm not very brilliant when it comes to programming)but when it comes to bash:scratch:

ntubski 09-29-2009 10:49 AM

The read command uses the value of IFS as its delimiter, so you can do this:
Code:

#!/bin/bash

while IFS=: read ip name dir ; do
    if [ -e "$dir/$ip" ] ; then
      echo "$name's backup file, $dir/$ip, exists"
    fi
done < users

find is overkill if you are just looking to check the existence of one file whose location is known, the test (aka [) command is what you need here.

You can read into an array with read -a arr, but I don't see any benefit in this case.

Jeroen1000 09-30-2009 04:50 AM

Hi ntubski,

I coughed up this after a while

Code:

#line="192.168.1.254:Jeff:dir"
#IFS=":"
#array=( $line )

#echo ${array[0]}


Now I can use your file finding snippet and I'm one step closer.

To give the bigger picture:

- Deltacopy is running on the Windows computers
- A script with root privileges is (via cron) invoked to start the backup.
The script chowns the users' backup dir to make sure that after the copy it has the correct user permissions.

Now, in the scenario where a user can invoke the backup with a PHP page where there is a 'backup now' button:

- When the user clicks on 'back up now' button, a file with the user ip will be created in the same dir as where the PHP script is.
- Root script will find out whether there are ip files and then invokes a
- user script which will make the backup (so it will call the Deltacopy server), chowns the files in the backup so the user has permission and then deletes the ip file (the root script will have set the correct permission so that the user script can delete this file).

In order for the user script to work, it needs the ip address and backup dir (which can be found in the 'users.txt' file). I want to pass these arguments in an array from the root script to the user script. That explains my use of the array.

Jeroen1000 09-30-2009 07:19 AM

okay I got some more:)
Code:

# First read the "users.txt" file into an array called "data".
# Each line of "data" represents a line of the "user.txt" text file.

USERS=/var/www/Deltacopy/users.txt
old_IFS=$IFS
IFS=$'\n'
data=($(cat $USERS))
IFS=$old_IFS
#echo ${data[0]}


The split part refuses I'm afraid. How do I split on : and put it in the variable ip?. At the moment it just strips the delimeter but doesn't put the first part into the variable ip...
Code:

# Next split each record of data to obtain the ip address.

old_IFS=$IFS
IFS=':'
ip= echo ${data[0]}
echo $ip


catkin 09-30-2009 07:45 AM

Quote:

Originally Posted by Jold_IFS=$IFS
IFS=':'
ip= echo ${data[0
}
echo $ip
[/CODE]

Bash assignments must not have spaces either side of the = operator and secondly echoing a variable sends its output to stdout whereas you want it to become the expression that is the source for the assignment so change to
Code:

ip="${data[0]}"
The double quotes are good practice, in case the variable value contains whitespace characters.

zhjim 09-30-2009 07:53 AM

Quote:

Originally Posted by Jeroen1000 (Post 3700503)
I knew enough PHP to get this done (I'm not very brilliant when it comes to programming)but when it comes to bash:scratch:

Hm if your familary with php why do you use bash? You could also use a php script to check on the existens of the files.

Code:

php -e /path/to/your/script
inside a cronjob would run your script. You could also do a

Code:

#!/bin/php
<?php
read dir
lookup in file
do backup
chown
cleanup
done
?>

If you still go with bash there is also the cut command which takes the delimiter after the argument -d and the filenumber after the -f argument. Also reading this into an array is not trivial if even possible.

Code:

arr[1]=$(cut -d : -f 0)
arr[2]=$(cut -d : -f 1)
arr[3]=$(cut -d : -f 2)

beside arr[#] this sure to work in bash.

cheers Zhjim


All times are GMT -5. The time now is 10:10 AM.