Shell script help

Hi guys - I have written this script to search for a file (mytest.txt) in the pwd. I was wondering how to:

  1. Implement multiple file directories inside the script
  2. Implement the file name inside the script

currently i run it as ./script_name.sh (file to search)

#!/bin/bash

# -------------------------------------------------------------------------
FILE="$1"
DIR=$(pwd)
# make sure we got file-name as command line argument
if [ $# -eq 0 ]
then
    echo "$0 file-name"
    exit 1
fi
 
which stat > /dev/null
 
# make sure stat command is installed
if [ $? -eq 1 ]
then
    echo "stat command not found!"
    exit 2
fi
 
# make sure file exists
if [ ! -e $FILE ]
then
    echo "$FILE not a file"
    exit 3
fi
 
# use stat command to get date info about the file

VAR="$(stat -c %y $FILE)"


VAR2="${VAR:0:10}"

NOW=$(date +"%Y-%m-%d")

if [ $NOW = $VAR2 ] 
then

echo "found file ($FILE) in $DIR"

else

echo "Not Found........."

fi

If all you want to do is find the file, just use:

find . -name FileName

This will find all instances of the file name you provide within the full hierarchy including and below the current location.

Actually its doing a little more than that.

I need to find out how to impletement directory paths and the file to search for inside this perticular script.

the find command will provide the path of each file found relative to the current pwd. You can also wrap the command in a loop to execute another function on each file...

#!/bin/bash
fileName=$1   # First parameter of the script call will be the file name.
for f in $(find . -name ${fileName}); do
    someFunction $f
done

You can use your stat call or any combination of functions on each file.

A little confused, not sure how to implement that.

What are you trying to accomplish? It looks like you might be trying to see if the file exists in the current folder and if it has some attribute that matches the current date. Is this correct?

Your current test for the existence of the file will only search the current folder where the script is executed. It will not search the sub folders. What do you mean you want to "implement directory paths" in this?

You are right, it is searching for a file and looking if it has current date. But it is only searching for current directory.

I am trying to search multiple directories for this check. Such as:

/home/student/dir1, /tmp/sys/dir1, /loc/var/sub and so on

I am also able to search with the file name in the command like ./script (file name), i am trying to implement the file name inside the script as well.

Your first variable assignment is FILE="$1". This takes the parameter (file name) that you passed in the ./script (file name) command and assigns it to the variable FILE. If you are only concerned about one file, you can simply hard code the name as FILE=(file name) in the script.

The code that I provided earlier:

#!/bin/bash
fileName=$1   # First parameter of the script call will be the file name.
for f in $(find . -name ${fileName}); do
    someFunction $f
done

Will search the current directory and all sub directories for the file name. For each instance that the find command matches, the for loop will execute the someFunction on the file. You can simply replace someFunction with the actions you want to perform on each file that was found.

Ok if i understood you correctly, i replaced the FILE"$1" to FILE=(somefile.txt).

Now when i run it, it gives me:

./script.sh file-name

Try this... Update the file name and starting search directory. FYI... you had your date comparison setup as an assignment rather than a comparison.

#!/bin/bash
NOW=$(date +"%Y-%m-%d")
FILE=(Enter the hard-coded file name here, i.e. fileName.txt)
DIR=(Enter the highest common directory in which you want to search, i.e. /startHere)

#############################
# Define functions
#############################

function checkStat
{
    # make sure stat command is installed
    which stat > /dev/null
    if [ $? -eq 1 ]; then
        echo "stat command not found!"
        exit 2
    fi
}

function processFile
{
    VAR="$(stat -c %y ${1})"
    VAR2="${VAR:0:10}"

    if [ $NOW == $VAR2 ]; then
        echo "found file ${1}"
    else
        echo "Not Found........."
    fi
}

#############################
# Main
#############################

checkStat
# Process all files
for f in $(find ${DIR} -name ${FILE}); do
    processFile $f
done

Now when I added more than one dir path, it only looks at the first one.

I added it like this:

#!/bin/bash
NOW=$(date +"%Y-%m-%d")
FILE=(osmap.txt)
DIR=( "/server_share1/loc/1" "/server_share2/loc/2" )

#############################

Don't put more than one path. Put only the highest common path. Of the two you listed...
/server_share1/loc/1
/server_share2/loc/2
the highest common path is the root directory (i.e. '/'), which is not recommended. If you need to specify only certain folders, then the script needs to change a bit. Before we go down this path, can you create a working folder and create soft links to each the folders you need to search? If so, set up the working folder and add "-L" without the quotes to the find command like find -L ${DIR} -name ${FILE}.

Just created soft links and a working directory. It worked. Thank you.

I just found an issue, i created a soft link that did not point to a real directory. When i ran the script, it did not catch that or throw an error.

Can you guide me how to add that?

what error is the script throwing?

If it cant find a directory, it dosent do anything and moves to the next one, without giving any error.

If it cant find todays file, it says "Not Found..." message. But does not show file path.

I am trying to accomplish:

  1. It should say "/path/to/dir" not found - when the directory isnt there
  2. It should say "/dir/file.txt is not new" - when the file isnt from current date, showing the directory path

Ok, perhaps a change in direction is worth considering... in your original post, you said you were searching for the files... your last post suggests that you know exactly where each file is and you just want to know if it is from the current date. Is this accurate?

I apologize, let me explain.

Your correction on my script does almost what i wanted it to do. But since there are many soft links its searches (~30), when it does not find a current file it only says "File Not Found". This output does not tell the reader where to search for this outdated file.

All I want it to do is to have a some error detection mechanism to alert when:

  1. when the directory isnt there (but since it searches only high level "/home/student/mylinks". im not sure how would it know if a soft link is missing?), the should be an error telling that the directory is missing

  2. if the file isnt current date, i should know which soft link has the old file. Instead of just getting "File not found", it should say for example, "File not found: /home/student/mylinks/dir1"

The first item requires a specific list of files, not simply a search. The search will find the files that exist and allow you to process them. If you want to know if a specific file cannot be access because it is missing or the link is broken, then you need to specifically list the file and test for its existence. If you know that there are X number of locations and those locations do not change, then the script can be written to check each of those locations specifically.

To address the second item, try editing the failure echo command in the processFile function to include the file name...

OLD:

echo "Not Found........."

NEW:

echo "Not Found: ${1}"

By adding

echo "Not Found: ${1}"

I was able to point to the directory having old file. It shows the dir path.

But the bigger problem seems to be issue no. 1

Mainly as when I removed the file all together OR removed the soft link, the check did not detect and passed it as "GOOD". (as you explained, it does what its supposed to do)

Any idea how to put directory and file availability check?

Thanks

Ok, so it sounds like you need three different types of responses:

  • File not found
  • File found, but not updated
  • File found and current

The script below takes a different approach. You will need to update the file name, log file location, and the array containing the list of directories. I'm rusty on arrays so it may not work as it is written.

#!/bin/bash
NOW=$(date +"%Y-%m-%d")

# Set the file names
FILE=fileName.txt
LOGFILE=${NOW}_FileCheck.log

# List the directories to search. DO NOT INCLUDE THE TRAILING SLASH
DIR=( "path/to/location1" "path/to/location2" )


#############################
# Define functions
#############################

function checkStat
{
    # make sure stat command is installed
    which stat > /dev/null
    if [ $? -eq 1 ]; then
        echo "stat command not found!"
        exit 2
    fi
}

function processFile
{
    if [ -f ${1} ]; then
        VAR="$(stat -c %y ${1})"
        VAR2="${VAR:0:10}"

        if [ $NOW == $VAR2 ]; then
            echo "Current File Found: ${1}" | tee -a ${LOGFILE}
        else
            echo "Old File Found: ${1}" | tee -a ${LOGFILE}
        fi
    else
        echo "File Not Found: ${1}" | tee -a ${LOGFILE}
    fi
}

#############################
# Main
#############################

# Verify the stat command exists
checkStat

# Create or clear the log file
echo "" > ${LOGFILE}

# Process the files
for f in ${DIR[@]}; do
    processFile ${f}/${FILE}
done