LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
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 12-17-2003, 07:28 AM   #16
Bebo
Member
 
Registered: Jul 2003
Location: Göteborg
Distribution: Arch Linux (current)
Posts: 553

Rep: Reputation: 31

Hello again,

I couldn't let it go (I like scripting ) so here is something that might work for you:

Code:
#!/bin/bash

declare -a names

names=(`find . -type d -name '*'`)
namesize=${#names[@]}

unset completename
unset previousname

for i in `seq 0 $namesize` ; do
    currentname=${names[$i]}

    if test $previousname ; then
	completename=`echo $completename $previousname`
	
	if test ! $currentname || test `echo $currentname | cut -c1-2` = './' ; then
	    echo "Here is the correct dirname for use: $completename"

            # DO SOMETHING HERE

	    unset completename
	fi
    fi

    previousname=$currentname
done

Cheers!

Last edited by Bebo; 12-17-2003 at 07:30 AM.
 
Old 12-17-2003, 09:08 AM   #17
dolmen
LQ Newbie
 
Registered: Dec 2003
Distribution: Mdk 9.2
Posts: 9

Rep: Reputation: 0
Re: Bash, LS, For loops, and whitespaces in directories

Quote:
Originally posted by jhrbek

The code below works for directories that do not have a whitespace, but will not include those that do.

Any help would be appreciated, thanks!


Code:
#!/bin/bash

# Build our directory list

for i in `ls`
 do
 if [ -d $i ]
  then
   echo "I found $i and it is a directory"
 fi
done
Of course, the simplest solution would be to use find as suggested by the first user who replied.

But I won't miss this occasion to teach you a few things.
Your original code has three flaws:[list=1][*]you are using ls instead of "ls".[*]you do not put quotes around variables.[*]you are using the ls result on the for line[/list=1]

Let's explain in depth:[list=1][*]ls may be an alias which may not be the same as expected when you wrote the shell script. In your case, ls seems to be "ls -CF" (as I see the '/' after the directories). Putting quotes (") around ls calls "bare" ls, bypassing any defined alias.
before: for i in `ls`
after: for i in `"ls"`[*]it is very important to put quotes around variable expansion because if the variable value is two or more words separated by spaces, they may be expanded as two separate words
before: if [ -d $i ]
after: if [ -d "$i" ][*]the numbers of rguments of some commands (may be the for statement) may be limited, so you can expect problems if your directory contains many files. You also have problems with filenames containing spaces because each part of the filename is used in a different iteration of the loop. The solution is to read line by line the result of "ls" in a variable.
before: for i in `ls`
after: "ls" | while read i[/list=1]

So the new code is :

Code:
#!/bin/bash

# Build our directory list

"ls" | while read i
do
  [ -d "$i" ] && echo "I found $i and it is a directory"
done
 
Old 12-17-2003, 09:17 AM   #18
dolmen
LQ Newbie
 
Registered: Dec 2003
Distribution: Mdk 9.2
Posts: 9

Rep: Reputation: 0
Bebo: don't try to transpose algorithms from other programming languages in shell programming because it is very apart. To be good in shell, you have to think in shell.
Using arrays in shell programming is usually not necessary.
 
Old 12-17-2003, 09:41 AM   #19
Bebo
Member
 
Registered: Jul 2003
Location: Göteborg
Distribution: Arch Linux (current)
Posts: 553

Rep: Reputation: 31
Hello dolmen,

I'm not sure if I understand what you mean. Where did I transpose algorithms from other programming languages? You mean the arrays? Well, with the inspiration of jhrbek, that was the only way I could think of to solve the problem with the iteration splitting the directory names. But, now with your post, I would have solved it differently using the double quotes. Thanks!

Edit: But, I don't get the double quotes to work around the find command. This works just as fine as my previous 25 line script:

Code:
find -type d -name '*' | while read name ; do
   echo $name
done
Wohoo!


Last edited by Bebo; 12-17-2003 at 09:54 AM.
 
Old 12-17-2003, 10:29 AM   #20
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,415
Blog Entries: 55

Rep: Reputation: 3594Reputation: 3594Reputation: 3594Reputation: 3594Reputation: 3594Reputation: 3594Reputation: 3594Reputation: 3594Reputation: 3594Reputation: 3594Reputation: 3594
Using arrays in shell programming is usually not necessary.
FWIW, I think arrays in shell programming are a deity gift. They can for instance help you cut down using external binaries. Here's a lame example. Say you got files all named "DDMM YYYY some_remark.ext" you have to rename to YYYYMMDD_some_remark.ext:
find . -type f -iname \*.ext | while read fn; do fn=( ${fn} )
D=${fn[0]:0:2} ); M=${fn[0]:2:2} ); Y=${fn[1]} );
mv "${fn[*]}" "${Y}${M}${D}_${fn[2]}"; done
In combination with IFS usage you could split on about any char ![0-9A-Za-z].
 
Old 12-17-2003, 06:15 PM   #21
dolmen
LQ Newbie
 
Registered: Dec 2003
Distribution: Mdk 9.2
Posts: 9

Rep: Reputation: 0
Quote:
Originally posted by Bebo
Hello dolmen,
I'm not sure if I understand what you mean. Where did I transpose algorithms from other programming languages? You mean the arrays?
Yes I mean the array. But may be I'm too used to program in shell without, because they are limited in ksh to 512 entries.

Quote:

Code:
find -type d -name '*' | while read name ; do
   echo $name
done
This code doesn't work as expected if a filename contains two (or more) consecutive spaces. Try running it after mkdir "a b" (with two spaces between 'a' and 'b').
So you have to put double quotes around the use of the variable.
And "-name '*'" doesn't add anything because "find" will already match all files (or did I miss something?).
This code is better:
Code:
find . -type d | while read name ; do
   echo "$name"
done
which in this particular case of the loop content can be reduced to "find . -type d -print"
 
Old 12-17-2003, 06:42 PM   #22
dolmen
LQ Newbie
 
Registered: Dec 2003
Distribution: Mdk 9.2
Posts: 9

Rep: Reputation: 0
Quote:
Originally posted by unSpawn
Here's a lame example. Say you got files all named "DDMM YYYY some_remark.ext" you have to rename to YYYYMMDD_some_remark.ext:
Code:
find . -type f -iname \*.ext | while read fn; do fn=( ${fn} )
D=${fn[0]:0:2} ); M=${fn[0]:2:2} ); Y=${fn[1]} ); 
mv "${fn[*]}" "${Y}${M}${D}_${fn[2]}"; done
In combination with IFS usage you could split on about any char ![0-9A-Za-z].
Here is my version (not tested, no Unix or GNU system around) :
Code:
find . -type f -iname \*.ext | sed s/\'/\\\\\''/g;/s/^\(..\)\(..\) \(....\) \(.*\).ext$/mv '\''\&'\'' '\''\3\2\1_\4.ext'\'/ | $SHELL
(this forum doesn't render double slashes as I want (slash before a quote disappear), and I won't fight against it. If you want my code, select the "quote" button).
 
Old 12-17-2003, 07:07 PM   #23
Bebo
Member
 
Registered: Jul 2003
Location: Göteborg
Distribution: Arch Linux (current)
Posts: 553

Rep: Reputation: 31
In reply to dolmen's post 21...

Well, yeah, I overlooked the double quotes again

About the -name '*'. Actually, I didn't think very much it in the beginning, as you can see in post 8. I realized the difference when I was writing my too-long script. The -name '*' will filter away the single period (.) which is the first element in find's output. I found that useful, somehow

It seems jhrbek has gotten his problem solved real good now, don't you think?
 
Old 12-17-2003, 08:44 PM   #24
dolmen
LQ Newbie
 
Registered: Dec 2003
Distribution: Mdk 9.2
Posts: 9

Rep: Reputation: 0
Quote:
Originally posted by Bebo
It seems jhrbek has gotten his problem solved real good now, don't you think?
I hope so.
 
Old 12-18-2003, 03:04 PM   #25
jhrbek
LQ Newbie
 
Registered: Dec 2003
Distribution: RedHat 8
Posts: 17

Original Poster
Rep: Reputation: 0
Wow, well thanks for all the help everyone! I haven't been able to work on this problem since tuesday because of final exams at university. I'm done now (just finished) so I'll be sure to implement the suggestions.

Dolmen,

I've tried quoting the LS command in the way you suggested but the for loop still split the directory names. Maybe it's something to do with redhat 8, I don't know. I don't know a whole lot about linux, but i'm trying to learn. Consequently, because of the mysterious for loop behavior, I decided to use find as it seems to be a bit more powerful than LS, at least for what I need to do.

Regardless, I'll definitely find a solution from all of these great suggestions. I'll be sure to post my final code at the end of the day today.

Thanks!

-j
 
Old 12-18-2003, 05:12 PM   #26
jhrbek
LQ Newbie
 
Registered: Dec 2003
Distribution: RedHat 8
Posts: 17

Original Poster
Rep: Reputation: 0
Finally!

Here is my final product, it does everything I need it to do. Thanks for all of your help!

Code:
for i in `ls`
 do
 if [ -d $i/user ]
  then
     find $spool/$i/user/ -type d | while read name ; do
      # We need to remove the spool path and get just the username
      name=${name//$escSpool\/$i\/user\//}
      if [ ! -z "$name" ]
       then
        echo "$name"
        echo "user/${name//^/.}" >>/tmp/userlist.txt
       echo -e "user.$name\tdefault\t${name//^/.}\tlrswipcda\t$acluser\tlrswipcda" >>/tmp/newmboxlist.txt
      fi
     done
 fi
done
 
Old 12-19-2003, 05:56 AM   #27
Bebo
Member
 
Registered: Jul 2003
Location: Göteborg
Distribution: Arch Linux (current)
Posts: 553

Rep: Reputation: 31
Great! I was a lot of fun!
 
Old 09-22-2010, 06:17 AM   #28
Bax1989
LQ Newbie
 
Registered: Sep 2010
Posts: 1

Rep: Reputation: 0
Thanks

I also had this question .
Bobe, your script works fine also without the "grep \/$" filter after the ls statement .
 
  


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
putty display loops on listing directories with many files, through expect script vineet.k Linux - General 5 03-13-2007 10:44 AM
Bash For Loops gives syntax error meadensi Linux - Newbie 2 02-23-2005 11:30 AM
bash scripting and loops phoeniks Programming 5 01-24-2005 05:00 PM
bash - while + until loops grouping? trees Linux - General 2 02-19-2004 03:29 PM
handling whitespaces in bash guerilla fighta Linux - General 2 01-25-2003 05:12 PM

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

All times are GMT -5. The time now is 04:31 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