LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
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


Reply
  Search this Thread
Old 05-22-2012, 10:49 PM   #1
newbiecolonopenparens
LQ Newbie
 
Registered: May 2012
Posts: 8

Rep: Reputation: Disabled
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?
 
Old 05-22-2012, 10:53 PM   #2
evo2
LQ Guru
 
Registered: Jan 2009
Location: Japan
Distribution: Mostly Debian and CentOS
Posts: 6,724

Rep: Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705
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.
Old 05-23-2012, 12:46 AM   #3
divyashree
Senior Member
 
Registered: Apr 2007
Location: Bangalore, India
Distribution: RHEL,SuSE,CentOS,Fedora,Ubuntu
Posts: 1,386

Rep: Reputation: 135Reputation: 135
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.
 
Old 05-23-2012, 03:51 PM   #4
newbiecolonopenparens
LQ Newbie
 
Registered: May 2012
Posts: 8

Original Poster
Rep: Reputation: Disabled
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?
 
Old 05-23-2012, 04:12 PM   #5
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
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.
Old 05-23-2012, 04:54 PM   #6
newbiecolonopenparens
LQ Newbie
 
Registered: May 2012
Posts: 8

Original Poster
Rep: Reputation: Disabled
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
Code:
argument=$1
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.
 
Old 05-23-2012, 05:17 PM   #7
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
Quote:
Originally Posted by newbiecolonopenparens View Post
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 View Post
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.
Old 05-23-2012, 05:27 PM   #8
newbiecolonopenparens
LQ Newbie
 
Registered: May 2012
Posts: 8

Original Poster
Rep: Reputation: Disabled
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!
 
Old 05-23-2012, 05:36 PM   #9
TobiSGD
Moderator
 
Registered: Dec 2009
Location: Germany
Distribution: Whatever fits the task best
Posts: 17,148
Blog Entries: 2

Rep: Reputation: 4886Reputation: 4886Reputation: 4886Reputation: 4886Reputation: 4886Reputation: 4886Reputation: 4886Reputation: 4886Reputation: 4886Reputation: 4886Reputation: 4886
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.
Old 05-23-2012, 06:26 PM   #10
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,358

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
Nice quote, and so true
 
Old 05-23-2012, 09:55 PM   #11
newbiecolonopenparens
LQ Newbie
 
Registered: May 2012
Posts: 8

Original Poster
Rep: Reputation: Disabled
nice book...
 
Old 05-23-2012, 10:38 PM   #12
divyashree
Senior Member
 
Registered: Apr 2007
Location: Bangalore, India
Distribution: RHEL,SuSE,CentOS,Fedora,Ubuntu
Posts: 1,386

Rep: Reputation: 135Reputation: 135
Quote:
Originally Posted by newbiecolonopenparens View Post
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.
 
Old 05-23-2012, 11:41 PM   #13
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Or, less error prone and more consistent: num=$(expr $(find $1 -type d | wc -l) - 1)
 
Old 05-23-2012, 11:53 PM   #14
evo2
LQ Guru
 
Registered: Jan 2009
Location: Japan
Distribution: Mostly Debian and CentOS
Posts: 6,724

Rep: Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705Reputation: 1705
While we're at it:
Code:
num=$(( $(find $1 -type d | wc -l) - 1))
Evo2.
 
Old 05-24-2012, 06:08 PM   #15
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
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
 
  


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
how to store result of wc -l command in variable? trynq Linux - Newbie 11 04-20-2011 07:49 AM
Shell variable storing the previously executed command late_nighter Linux - Newbie 2 05-23-2010 01:50 PM
Trouble storing a variable in a shell script after awk output uncle-c Linux - Newbie 3 02-08-2010 07:13 AM
Storing password used in shell scripts in encrypted file Swakoo Linux - Security 2 12-06-2006 10:39 PM
storing output of sed in a variable in shell script Fond_of_Opensource Linux - Newbie 1 11-09-2006 03:57 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

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