LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-17-2010, 10:02 AM   #1
faizlo
Member
 
Registered: Sep 2008
Location: USA
Distribution: Linux Mint Qiana
Posts: 190

Rep: Reputation: Disabled
bash: feeding input to a script from a text file


Hi all,

I have a script which checks on my jobs that run on some cluster.
The script, "script.sh", takes as an input the job-id for the job to be checked. Sometimes I have 100s of jobs and I want to check them all (for successful completion.) I could put these job-ids into a text file, "job-id.txt", each id in its own line.
For each job-id, the script would ask me few questions (with a yes or no answers) to see if I want to do some other checks for each job-id.

I want to know how may I direct my job-ids from this text file into the script one job-id at a time.

Thanks in advance,

~faizlo
 
Old 11-17-2010, 10:10 AM   #2
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556
You could do something like this, using xargs:
Code:
xargs -a job-id.txt -I@ ./script.sh @
This provides similar functionality to doing a while/done loop in the shell, and feeding it the job-id.txt file with a re-direct:
Code:
while read line; do
 # "$line" is the job ID
 # ask questions here
done < job-id.txt
which is also (nearly) the same as doing it this way:
Code:
cat job-id.txt | while read line; do
 # "$line" is the job ID
 # ask questions here
done
 
Old 11-17-2010, 10:11 AM   #3
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

Something like this should work:

Code:
#!/bin/bash

for JOBID in `cat job-id.txt`
do

  --- your code goes here, $JOBID holds 1 entry ---

done
Hope this helps.
 
Old 11-17-2010, 11:02 AM   #4
faizlo
Member
 
Registered: Sep 2008
Location: USA
Distribution: Linux Mint Qiana
Posts: 190

Original Poster
Rep: Reputation: Disabled
@GrapefruiTGirl:
xargs yielded echoing the help message for xargs claiming that -a is not a valid option. I checked the man pages and -a is a valid option to feed from a file (instead of std input).
Adding the while loop in the script is a very good idea. I added my script here as I thought this may help because I did not know how/where to add the loop (sorry)

@druuna
I used your script as follows:
Code:
#!/bin/bash

for JOBID in `cat job-id.txt`
do

  ./script.sh $JOBID

done
And it worked fine. Thank you both so much for the quick help and wonderful ideas.

Well, your help honed my appetite to ask for more!

Since this script (script.sh) asks for job ids as an input, one at a time, I have to answer few questions with y or n.
How should I edit the script such that if any of the output messages contain: NO FILES TO RECOVER, it would discontinue checking and fall back to the next job-id?

here is my script:
Code:
check()
{
    echo "Do you want to proceed?"
    read answer
    if [ "${answer}" == "y" ] ; then
	echo "... proceeding ..."
    else
	echo "Aborting."
	exit 1
    fi
}


project=$1

echo "Make a recovery project: ${project}"
echo "First, look at the project summary."
check

echo "project summary --project=${project}"
project summary --project=${project}

echo "Now get the recovery dims."
check

echo "recovery project --printQuery --project=${project}"
dims=`recovery project --printQuery --project=${project}`

echo "$dims"
echo "Translate these dims."
check

echo "get --dims=\"${dims}\""
get --dims="${dims}"

echo "Create the recovery definition."
check

echo "definition --group=dzero --defName=recovery_project_${project} --dims=\"${dims}\""
definition --group=user --defName=recovery_project_${project} --dims="${dims}"

echo "Now check the definition."
#check

echo "get --summaryOnly --dims=\"__set__ recovery_project_${project}\""
get --summaryOnly --dims="__set__ recovery_project_${project}"

echo "DONE!"
echo "Recovery def: recovery_project_${project}"
thanks again

~faizlo

Last edited by faizlo; 11-17-2010 at 11:05 AM.
 
Old 11-17-2010, 11:10 AM   #5
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556
Interesting.. I wonder why xargs -a did not work for you.. If you're interested, you could try the --long version of -a, which is --arg-file= instead of -a. So it would look like:
Code:
xargs --arg-file=job-id.txt -I@ ./script.sh @
Anyhow, even if this mysteriously does not work, I believe you're well along the way to a good solution. Let us know if any further troubles crop up, or you need more help.
 
Old 11-17-2010, 11:27 AM   #6
faizlo
Member
 
Registered: Sep 2008
Location: USA
Distribution: Linux Mint Qiana
Posts: 190

Original Poster
Rep: Reputation: Disabled
Yes, I still need some help.
Your loop idea is nice but I am not sure I know how should I add the loop into the script?

~faizlo

I tried xargs on both tcsh (which is my main shell, but not my shell of chice ) and on a bash terminal, both gave same complains about the -a option!
Also, the --arg-file= option did not work too!!! It threw the same help message.
 
Old 11-17-2010, 11:46 AM   #7
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556
Code:
check()
{
    echo "Do you want to proceed?"
    read answer
    if [ "${answer}" == "y" ] ; then
	echo "... proceeding ..."
    else
	echo "Aborting."
	exit 1
    fi
}

while read project; do
#project=$1

echo "Make a recovery project: ${project}"
echo "First, look at the project summary."
check

echo "project summary --project=${project}"
project summary --project=${project}

echo "Now get the recovery dims."
check

echo "recovery project --printQuery --project=${project}"
dims=`recovery project --printQuery --project=${project}`

echo "$dims"
echo "Translate these dims."
check

echo "get --dims=\"${dims}\""
get --dims="${dims}"

echo "Create the recovery definition."
check

echo "definition --group=dzero --defName=recovery_project_${project} --dims=\"${dims}\""
definition --group=user --defName=recovery_project_${project} --dims="${dims}"

echo "Now check the definition."
#check

echo "get --summaryOnly --dims=\"__set__ recovery_project_${project}\""
get --summaryOnly --dims="__set__ recovery_project_${project}"

echo "DONE!"
echo "Recovery def: recovery_project_${project}"

done < job-id.txt
I made a couple small changes in your script above, and put them as bold text. This is probably not exactly how I would do this if I were writing this script for myself, but it demonstrates one way of implementing a loop that reads the items from the input file, and executes a bunch of code (everything between the while read and the done < blah blah.. parts) for each item.

So now, every time you run the above script, it will process the job-id.txt file, and loop through all entries inside it, asking you what to do. If you abort, then the entire process is aborted, so you might want to further adjust the code if you have the need to be able to skip a job, but not abort the whole process.
 
Old 11-17-2010, 11:46 AM   #8
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

Would this help?
Code:
#!/bin/bash
# -------------------------------------------------------------------------- #
# Variables
# ------------------------------------------------------------------ #

[[ "$1" == "" ]] && echo "syntax script.sh jobidfile" ; exit 1

project="$1"

# -------------------------------------------------------------------------- #
# Functions
# ------------------------------------------------------------------ #
check()
{
    echo "Do you want to proceed?"
    read answer
    if [ "${answer}" == "y" ] ; then
     echo "... proceeding ..."
    else
     echo "Aborting."
     exit 1
    fi
}


# -------------------------------------------------------------------------- #
# Main
# ------------------------------------------------------------------ #

for JOBID in `cat ${project}`
do

  echo "Make a recovery project: ${project}${JOBID}"
  echo "First, look at the project summary."
  check

  echo "DONE!"
  echo "Recovery def: recovery_project_${project}${JOBID}"

done

exit 0

# -------------------------------------------------------------------------- #
# End
I just placed the first and last commands you posted in post #4 inside the loop. So the above is now your script.sh

Hope this helps.

Last edited by druuna; 11-17-2010 at 12:31 PM. Reason: Fixed dumb mistake, see post #9
 
Old 11-17-2010, 12:09 PM   #9
faizlo
Member
 
Registered: Sep 2008
Location: USA
Distribution: Linux Mint Qiana
Posts: 190

Original Poster
Rep: Reputation: Disabled
@druuna
Shouldn't it be like this:
Code:
#!/bin/bash
# -------------------------------------------------------------------------- #
# Variables
# ------------------------------------------------------------------ #

[[ "$1" == "" ]] && echo "syntax script.sh jobidfile" ; exit 1

project="$1"

# -------------------------------------------------------------------------- #
# Functions
# ------------------------------------------------------------------ #
check()
{
    echo "Do you want to proceed?"
    read answer
    if [ "${answer}" == "y" ] ; then
     echo "... proceeding ..."
    else
     echo "Aborting."
     exit 1
    fi
}


# -------------------------------------------------------------------------- #
# Main
# ------------------------------------------------------------------ #

for JOBID in `cat ${project}`
do

  echo "Make a recovery project: $JOBID"
  echo "First, look at the project summary."
  check

  echo "DONE!"
  echo "Recovery def: recovery_project_$JOBID"

done

exit 0

# -------------------------------------------------------------------------- #
# End
 
Old 11-17-2010, 12:23 PM   #10
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

Yes, of course...... Stupid of me! Sorry.
 
Old 11-17-2010, 12:39 PM   #11
tuxdev
Senior Member
 
Registered: Jul 2005
Distribution: Slackware
Posts: 2,012

Rep: Reputation: 115Reputation: 115
Don't use the for file in `cat file` form, it's quite fragile and depends too much on what IFS happens to be at the time. The while-read form is *much* more robust. (also, $() is way better than backticks)
 
1 members found this post helpful.
Old 11-17-2010, 01:18 PM   #12
faizlo
Member
 
Registered: Sep 2008
Location: USA
Distribution: Linux Mint Qiana
Posts: 190

Original Poster
Rep: Reputation: Disabled
Also, the first exit statement
exit 1 (at checking the input file statement) caused the whole script to exit with an exit status 1
I made a small adjustment:
Code:
#!/bin/bash

# -------------------------------------------------------------------------- #
# Variables
# -------------------------------------------------------------------------- #

if [ $# -lt 1 ]; then 
    echo "syntax make_recovery_project.sh job-id.txt";
    exit 1
fi

project="$1"


# -------------------------------------------------------------------------- #
# Functions
# -------------------------------------------------------------------------- #
check()
{
    echo "Do you want to proceed?"
    read answer
    if [ "${answer}" == "y" ] ; then
     echo "... proceeding ..."
    else
     echo "Aborting."
     exit 1
    fi
}


# -------------------------------------------------------------------------- #
# Main
# -------------------------------------------------------------------------- #

for JOBID in `cat ${project}`
do

echo "Make a recovery def for project:" $JOBID
echo "First, look at the project summary."
check

echo "get project summary --project="$JOBID
nofiles=`get project summary --project=$JOBID | grep -c \"NO FILES TO RECOVER\"`
if [ "$nofiles" != 0 ]; then
    echo "Nothing to do for this job, go to the next job ID ..."
    continue
fi

echo "Now get the recovery dims."
check

echo "generate strict recovery project --printQuery --project="$JOBID
dims=`generate strict recovery project --printQuery --project=$JOBID`

echo "$dims"
echo "Translate these dims."
check

echo "translate --dims=\"${dims}\""
translate --dims="${dims}"

echo "Create the recovery definition."
check

echo "create definition --group=dzero --defName=recovery_project_$JOBID --dims=\"${dims}\""
create definition --group=dzero --defName=recovery_project_$JOBID --dims="${dims}"

echo "Now check the definition."
#check

echo "translate --summaryOnly --dims=\"__set__ recovery_project_$JOBID\""
translate --summaryOnly --dims="__set__ recovery_project_$JOBID"

echo "DONE!"
echo "Recovery def: recovery_project_$"JOBID

done

exit 0

# -------------------------------------------------------------------------- #
# End
I will try it now!

~faizlo

Last edited by faizlo; 11-18-2010 at 01:17 PM.
 
Old 11-17-2010, 01:21 PM   #13
faizlo
Member
 
Registered: Sep 2008
Location: USA
Distribution: Linux Mint Qiana
Posts: 190

Original Poster
Rep: Reputation: Disabled
@tuxdev

Do you mean, instead of
Code:
for JOBID in `cat ${project}`
I should have
Code:
for JOBID in $(cat ${project})
?
 
Old 11-17-2010, 08:07 PM   #14
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192
No he means instead of the for loop construct which is subject to word splitting based on IFS that you need to change it to the while loop construct
shown by GGirl, ie:
Code:
while read -r JOBID
do
    <your stuff here>
done< $project
I would also mention that your first test is not robust enough in that the user may also enter more than one parameter, which I believe is unacceptable. Plus
what if the file entered does not exist? Maybe we could using something like:
Code:
if (( $# != 1 )) && [[ ! -e "$1" ]]
then
    echo "syntax make_recovery_project.sh job-id.txt"
    exit 1
fi
 
Old 11-18-2010, 01:17 PM   #15
faizlo
Member
 
Registered: Sep 2008
Location: USA
Distribution: Linux Mint Qiana
Posts: 190

Original Poster
Rep: Reputation: Disabled
Hi again,

so I tried the loop part as suggested by GrapefruiTGirl and grail,
I could get this:
Code:
./recover_jobs.sh jobs-id.txt
Make a recovery def for project: 31980_20101114093600
First, look at the project summary.
Do you want to proceed?
Aborting.
which could read the first project id correctly but for some reason did not not ask me to answer y or anything else and just aborted!

Any hint?
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Feeding input to interactive programs in bash babaqga Linux - Newbie 4 08-31-2010 10:17 AM
How to read a text file using a bash script Jeroen1000 Programming 8 09-30-2009 06:53 AM
bash script to create text in a file or replace value of text if already exists knightto Linux - Newbie 5 09-10-2008 11:13 PM
Bash script to edit text file snowman81 Linux - Desktop 2 01-10-2007 03:33 PM
Change Text-File through bash script arkus Programming 2 12-17-2004 08:48 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:41 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration