LinuxQuestions.org
Help answer threads with 0 replies.
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 03-11-2009, 01:04 AM   #1
kylebarbour
LQ Newbie
 
Registered: Mar 2009
Distribution: Debian
Posts: 6

Rep: Reputation: 0
Bash: proceeding only if a string from a for loop does *not* match some value


Hello there,

I'm trying to write a script in bash which cycles through all the users on the system who have a home directory, and then executes some code for each user. I did this as follows:

Code:
for user in $( ls /home); do
    whatever
done
This works fine, except it includes the lost+found directory as a user. So, I tried

Code:
for user in $( ls /home); do
    if [ $user!=lost+found ]; then
       whatever
    fi
done
However, when run, this still includes "lost+found" as if it were a user (in fact, it runs as if the if statement didn't exist). What am I doing wrong here?

Thanks so much.

Kyle
 
Old 03-11-2009, 01:08 AM   #2
ciotog
Member
 
Registered: Mar 2004
Location: Canada
Distribution: Slackware current
Posts: 728
Blog Entries: 2

Rep: Reputation: 43
Code:
if [ $user!=lost+found ]
should be
Code:
if [ ! $user = lost+found ]
update:
Actually there's nothing wrong with != for a test string equality expression, but perhaps because it wasn't surrounded by spaces it wasn't working. I would also put the strings in quotes, and add 'X' just in case $user comes out empty. So I would write it like this:
Code:
if [ "X$user" != "Xlost+found" ]

Last edited by ciotog; 03-11-2009 at 09:24 AM. Reason: add update
 
Old 03-11-2009, 01:10 AM   #3
kylebarbour
LQ Newbie
 
Registered: Mar 2009
Distribution: Debian
Posts: 6

Original Poster
Rep: Reputation: 0
Thank you so much! That completely fixed the problem. Awesome!

Kyle
 
Old 03-11-2009, 02:54 AM   #4
kylebarbour
LQ Newbie
 
Registered: Mar 2009
Distribution: Debian
Posts: 6

Original Poster
Rep: Reputation: 0
Unfortunately, with a little closer inspection, this still doesn't quite work. Here's the script that I wrote, to make some fortune files and copy them to /usr/share/games/fortunes, incorporating the [ ! $user=lost+found ] correction:

Code:
fdir=/usr/share/games/fortunes

for user in $( ls /home ); do
    ff=/home/$user/.fortunes

    if [ -f $ff ]; then
        cp $ff $fdir/fortunes-$user
        cd $fdir
        strfile fortunes-$user
    elif [ ! $user=lost+found ]; then
        echo "No fortune file found for $user. Moving on."
    fi
done
However, if I create the directory /home/test, the script does not echo the "no fortune file found for test" line - it acts as if it's not there. Any thoughts as to why this might not be happening? Is this part of a faulty test condition, or is it something else in the script?

Kyle

Update: I just realized that this probably would work if I had put spaces around the equals sign - I didn't notice that earlier. Ultimately, that was the problem.

Last edited by kylebarbour; 03-12-2009 at 03:37 AM.
 
Old 03-11-2009, 04:22 AM   #5
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,361
Blog Entries: 55

Rep: Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547
Excluding it right from the start seems cleaner. Given the fact no username will have a plus sign in their name, you could probably use something like
'find /home -maxdepth 1 -type d | while read DIR; do [ "${DIR:10:1}" = "+" -o ${#DIR} -eq 5 ] || echo "doSomething $DIR"; done' instead of "/home/lost+found". Use 'set -x' to test your script and see what variables get populated how. Usually helps when debugging.
 
Old 03-11-2009, 06:28 AM   #6
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,882

Rep: Reputation: 567Reputation: 567Reputation: 567Reputation: 567Reputation: 567Reputation: 567
Here's another idea:
Code:
fdir=/usr/share/games/fortunes

for user in $( ls -1 /home |grep -v lost+found ); do
    ff=/home/$user/.fortunes

    if [ -f $ff ]; then
        mkdir -p $fdir/fortunes-$user
        cp $ff $fdir/fortunes-$user
        cd $fdir
        strfile fortunes-$user
    else
        echo "No fortune file found for $user. Moving on."
    fi
done
What is strfile?
 
Old 03-11-2009, 07:40 PM   #7
kylebarbour
LQ Newbie
 
Registered: Mar 2009
Distribution: Debian
Posts: 6

Original Poster
Rep: Reputation: 0
@gnashley:

Beautiful! That seems to work perfectly (update: although I left out the directory creation). Thanks! As a curiosity, do you have any idea why [ $user!=lost+found ] doesn't work (or [ ! $user=lost+found ], as the case may be)?

strfile(1) creates a database from a percent-separated source file that gives fortune(6) the information it needs to randomly select fortunes from the source file. (Basically, it creates a database with the beginning and ending line numbers of each fortune based on where you've put percent signs or some other delimiter of your choice.) So, if you have the fortune file 'fortunes' with contents

Code:
Love conquers all. --Virgil
%
A mathematician is a machine for turning coffee into theorems.

  -- Alfréd Rényi
%
EVIL! PURE AND SIMPLE FROM THE EIGHTH DIMENSION!
%
then 'strfile fortunes' (in essence, anyway) will produce a file called 'fortunes.dat' which says that there are 3 fortunes, that the Virgil quote is on line 1 and ends on line 1, the Rényi quote begins on line 3 and ends on line 5, and that the Buckaroo Banzai quote begins and ends on line 7. This lets fortune(6) randomly access a quote without needing to parse through the entire source file.

See 'man 6 fortune' and 'man 1 strfile' for more detail.

@unSpawn:

Didn't know about set -x - thanks! I was wondering if there was something like that so that I could see how the program was being parsed.

Last edited by kylebarbour; 03-11-2009 at 08:12 PM.
 
Old 03-11-2009, 07:47 PM   #8
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,361
Blog Entries: 55

Rep: Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547
Actually the '$( ls -1 /home |grep -v lost+found )' could be replaced by one command (efficiency) doing something like 'find /home -maxdepth 1 -type d -not -name lost+found'.
 
Old 03-11-2009, 08:04 PM   #9
kylebarbour
LQ Newbie
 
Registered: Mar 2009
Distribution: Debian
Posts: 6

Original Poster
Rep: Reputation: 0
@unSpawn: Sure, that seems reasonable.

@ciotog: Just saw that you'd updated your post. You're right! It's the spacing. [ $something != something-else ] works perfectly, while [ $something!=something-else ] doesn't work at all. I wonder if test treated the whole thing as a single string, which would of course always validate as true.

Mystery solved! Thanks, everyone.

Update:

@unSpawn: Unfortunately, 'find /home -maxdepth 1 -type d ! -name lost+found' outputs '/home/kyle', '/home/test', etc., rather than just 'kyle' and 'test'. There might be a way to fix that, but I don't know what it is. Thanks for the thought anyhow, though!

Last edited by kylebarbour; 03-11-2009 at 08:10 PM.
 
Old 03-11-2009, 08:16 PM   #10
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,361
Blog Entries: 55

Rep: Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547
Quote:
Originally Posted by kylebarbour View Post
Unfortunately, 'find /home -maxdepth 1 -type d ! -name lost+found' outputs '/home/kyle', '/home/test', etc., rather than just 'kyle' and 'test'.
Chop it off: 'find /home -maxdepth 1 -type d ! -name lost+found|while read DIR; do [ -n "${DIR:6}" ] && echo "doSomething ${DIR:6}"; done'. Or use $(basename ${DIR}) if you need more compatibility or just don't like Bash-isms.

Last edited by unSpawn; 03-11-2009 at 08:17 PM.
 
Old 03-12-2009, 04:20 AM   #11
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,882

Rep: Reputation: 567Reputation: 567Reputation: 567Reputation: 567Reputation: 567Reputation: 567
find /home/* -maxdepth 1 -type d ! -name lost+found
 
Old 03-12-2009, 05:25 AM   #12
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,361
Blog Entries: 55

Rep: Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547Reputation: 3547
Quote:
Originally Posted by gnashley View Post
find /home/* -maxdepth 1 -type d ! -name lost+found
Globbing works here but only because there's usually no dirnames at this level that start with a dot. I mean it doesn't automagically work everywhere. At least for me that's a reason to avoid that kind of globbing reflex as much as I can.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
how to loop over text file lines within bash script for loop? johnpaulodonnell Linux - Newbie 9 07-28-2015 04:49 PM
bash loop within a loop for mysql ops br8kwall Programming 10 04-30-2008 04:50 AM
iptables string match htb Linux - Networking 2 08-30-2006 03:37 PM
iptables string match kahpeetan Linux - Security 3 11-09-2003 07:36 PM
how to grep only one string pr match gummimann Linux - General 3 11-06-2003 10:40 AM

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

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

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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration