Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place! |
| Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
 |
GNU/Linux Basic Guide
This 255-page guide will provide you with the keys to understand the philosophy of free software, teach you how to use and handle it, and give you the tools required to move easily in the world of GNU/Linux. Many users and administrators will be taking their first steps with this GNU/Linux Basic guide and it will show you how to approach and solve the problems you encounter.
Click Here to receive this Complete Guide absolutely free. |
Due to network maintenance being performed by our provider, LQ will be down starting at 05:01 AM UTC. The exact duration of the downtime isn't currently known. We apologize for the inconvenience.
|
 |
05-22-2012, 10:49 PM
|
#1
|
|
LQ Newbie
Registered: May 2012
Posts: 8
Rep: 
|
shell scripts: storing result of a command into a variable
hi there guys, I have a question to ask.
Let's say I typed in the command: find $1 -type d | wc -l
to find the number of directories. This command, from what I discovered in previous threads, gives 1 extra directory. That's not what I want. I want to do subtract 1 from this result and output it to my terminal.
Let's assume I have a shell script called "checkD."
An example would be:
$ checkD ~/direct/here
5
// I want it to output 4, but how would I do that?
I would assume I store that result into a variable, such as
num="find $1 -type d | wc -l" , or something along the lines.
What would be the correct way to modify that '5' into a 4 in my bash shell script?
|
|
|
|
05-22-2012, 10:53 PM
|
#2
|
|
Senior Member
Registered: Jan 2009
Location: Japan
Distribution: Debian
Posts: 3,588
|
Hi,
assuming bash (or similar), I think you are looking for something like the following
Code:
# Store the output in the variable $num
num=$(find $1 -type d | wc -l)
echo $num
# Decrease $num by one
((num--))
echo $num
Cheers,
Evo2.
|
|
|
1 members found this post helpful.
|
05-23-2012, 12:46 AM
|
#3
|
|
Senior Member
Registered: Apr 2007
Location: bbsr,orissa,India
Distribution: RHEL5 ,RHEL4,CENT OS5,FEDORA,
Posts: 1,261
Rep: 
|
YOu can use like this also:
Quote:
num=$(expr `find $1 -type d | wc -l` - 1)
echo $num
|
Last edited by divyashree; 05-23-2012 at 12:51 AM.
|
|
|
|
05-23-2012, 03:51 PM
|
#4
|
|
LQ Newbie
Registered: May 2012
Posts: 8
Original Poster
Rep: 
|
Thank you for the prompt responses, divayashree and evo2.
evo2's code worked just fine. It was exactly what I needed.
However, divayashree's did not work. It looks a bit cleaner though. I got the error "expr: non-numeric argument"
Is there a way to make it work with expr?
|
|
|
|
05-23-2012, 04:12 PM
|
#5
|
|
Moderator
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.4 OpenSuSE 12.2
Posts: 9,896
|
Just out of curiosity, what is this extra directory you mentioned? Maybe there is a way to exclude it from the result using the proper predicates of the find command. For example, if you want to find the sub-directories contained in the main directory and exclude the main directory itself from the output:
Code:
find $1 -mindepth 1 -type d
|
|
|
1 members found this post helpful.
|
05-23-2012, 04:54 PM
|
#6
|
|
LQ Newbie
Registered: May 2012
Posts: 8
Original Poster
Rep: 
|
The extra directory is the current directory. It includes itself in the count when I do:
Code:
find $i -type d | wc -l
colucix, that line of code definitely prints out all sub-directories, but I'm trying to get the number of folders, where the argument comes from command line arguments.
Another question: I want to iterate through each of the command line arguments. I understand that
will store my first argument in there. ((argument++)) won't work. I've tried googling for the answer, but nothing much has helped. An example would be:
Code:
$ checkD ~/Desktop ~/Music
How do I iterate 'argument' from $1 to $2, and from $2 to $3, and so on?
I'm expecting something like
Code:
argument=$1
count=1
end=$#
while( count != end )
do
echo $argument
((count++))
shift 1
done
a C++ equivalent would be
Code:
int main( int argc , char* argv[] ){
int i = 1;
while( i < argc )
cout << argv[i] << ' ';
i++;
}
Last edited by newbiecolonopenparens; 05-23-2012 at 05:02 PM.
|
|
|
|
05-23-2012, 05:17 PM
|
#7
|
|
Moderator
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.4 OpenSuSE 12.2
Posts: 9,896
|
Quote:
Originally Posted by newbiecolonopenparens
colucix, that line of code definitely prints out all sub-directories, but I'm trying to get the number of folders, where the argument comes from command line arguments.
|
So pipe the output to wc -l as you did in your example. Or am I missing something?
Code:
n=$(find $1 -mindepth 1 -type d | wc -l)
My remark was that a workaround is not necessary (subtracting 1 from the result) if the source of the problem can be fixed.
Quote:
Originally Posted by newbiecolonopenparens
Another question: I want to iterate through each of the command line arguments.
|
Using shift as you already tried. However you must not increase the argument number, since arguments are moved to the left and the current one is always $1. Example:
Code:
until [[ -z "$1" ]]
do
echo "$1"
shift
done
|
|
|
1 members found this post helpful.
|
05-23-2012, 05:27 PM
|
#8
|
|
LQ Newbie
Registered: May 2012
Posts: 8
Original Poster
Rep: 
|
haha I didn't realize that I could've piped
Code:
find $1 -mindepth 1 -type d
also, I iterated through the arguments differently.
Code:
for argument in $*
do
...
done
hooray for being new to scripting. Thanks for the help everyone!
|
|
|
|
05-23-2012, 05:36 PM
|
#9
|
|
Moderator
Registered: Dec 2009
Location: Hanover, Germany
Distribution: Slackware
Posts: 12,174
|
Bash Beginners Guide, Section 3.2.5:
Quote:
$* vs. $@
The implementation of "$*" has always been a problem and realistically should have been replaced with the behavior of "$@". In almost every case where coders use "$*", they mean "$@". "$*" Can cause bugs and even security holes in your software.
|
|
|
|
1 members found this post helpful.
|
05-23-2012, 06:26 PM
|
#10
|
|
Guru
Registered: Aug 2004
Location: Brisbane
Distribution: Centos 6.4, Centos 5.9
Posts: 14,993
|
Nice quote, and so true 
|
|
|
|
05-23-2012, 09:55 PM
|
#11
|
|
LQ Newbie
Registered: May 2012
Posts: 8
Original Poster
Rep: 
|
nice book...
|
|
|
|
05-23-2012, 10:38 PM
|
#12
|
|
Senior Member
Registered: Apr 2007
Location: bbsr,orissa,India
Distribution: RHEL5 ,RHEL4,CENT OS5,FEDORA,
Posts: 1,261
Rep: 
|
Quote:
Originally Posted by newbiecolonopenparens
Thank you for the prompt responses, divayashree and evo2.
evo2's code worked just fine. It was exactly what I needed.
However, divayashree's did not work. It looks a bit cleaner though. I got the error "expr: non-numeric argument"
Is there a way to make it work with expr?
|
Have you used the backtick as I mentioned , without which it will give error ...
marked in red bold,
Quote:
|
num=$(expr `find $1 -type d | wc -l` - 1)
|
Last edited by divyashree; 05-23-2012 at 10:41 PM.
|
|
|
|
05-23-2012, 11:41 PM
|
#13
|
|
LQ 5k Club
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian Squeeze (server), Slackware 13.37 (netbook), Slackware64 14.0 (desktop),
Posts: 8,357
|
Or, less error prone and more consistent: num=$(expr $(find $1 -type d | wc -l) - 1)
|
|
|
|
05-23-2012, 11:53 PM
|
#14
|
|
Senior Member
Registered: Jan 2009
Location: Japan
Distribution: Debian
Posts: 3,588
|
While we're at it:
Code:
num=$(( $(find $1 -type d | wc -l) - 1))
Evo2.
|
|
|
|
05-24-2012, 06:08 PM
|
#15
|
|
Bash Guru
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,577
|
Note that using wc to count the number of files is subject to some error. It's possible for file/directory names to contain newline characters themselves, and they would be counted as multiple files using this technique.
A more robust approach would be to output the files into an array using the -print0 option, and using that to get the count and to iterate over them.
Some appropriate links:
http://mywiki.wooledge.org/BashFAQ/004
http://mywiki.wooledge.org/BashFAQ/005
http://mywiki.wooledge.org/BashFAQ/020
bash v4+ has a new globstar option that, in simple cases, can replace find. (although I've found it to still be buggy when operating on certain large directory trees.)
http://wiki.bash-hackers.org/syntax/expansion/globs
Code:
#!/bin/bash
shopt -s globstar dotglob #set dotglob to count hidden directories as well
dirs=( "$1"/**/ )
#or using find
#while IFS= read -r -d '' ; do
# dirs+=( "$REPLY" )
#done < <( find "$1" -type d -print0 )
echo "The number of subdirectories in $1 is: $(( ${#dirs[@]} -1 ))"
for dir in "${dirs[@]}"; do
[[ $dir -ef "$1" ]] && continue #skip processing if it's the starting directory
echo "This is a command being applied to $dir"
done
exit 0
|
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -5. The time now is 10:01 PM.
|
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|