LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
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 01-25-2013, 06:15 AM   #1
RandyTech
Member
 
Registered: Oct 2010
Posts: 62

Rep: Reputation: 3
bash script problem -- pass complex *one-liner* to a variable


I found a one-liner on another forum:
http://superuser.com/questions/32183...es-recursively
This one-liner used here to illustrate the syntax problem I encounter with many so-called one-liners ... it does exactly what I need (almost). First problem I encountered (and not so significant to me per say), it does not work for me at line command or inside a bash script as a "one-liner" but works fine inside a script (where I need it) if I break it down as seen in the following code sample.

The real main problem I encounter is I cannot get the results *into a variable*. Tried every angle I can think of and googled it to death. I'm stuck. Can anyone offer proper syntax to place output from this snippit into a variable:
Code:
find /etc/sysconfig/ -type d | while read dir
do
  echo "$dir" : $(find "$dir" -type f | wc -l)
done | sort -k2 -t ':' -n |head -n 1
If it would work, I imagine the one-liner would look something like this:
Code:
MyVar=`find /etc/sysconfig/ -type d | while read dir ; do ; echo "$dir" : $(find "$dir" -type f | wc -l) ; done | sort -k2 -t ':' -n |head -n 1`
In the above one-liner (and in a perfect world), the "MyVar" variable would give me the path to the directory with the fewest file count. I don't need the one-liner to work as long as I can get the same results into "MyVar".

The true objective to this post is looking for insight on this *complex one-liner* issue -- not being able to figure out proper syntax to get the results into a variable. I encounter this same problem with many so called one-liners -- they give the desired results but how to get those results into a variable?

PS: Yes I know the single path returned in my sample snippet is not the *only* empty directory. That is not a concern. The point to the snippit is to find *at least one* path with the fewest files, regardless how many other paths may have the same file count.
 
Old 01-25-2013, 06:27 AM   #2
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,850

Rep: Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309
this worked for me as one-liner and script too. bash 3.2.51(1). Which shell did you try?
 
Old 01-25-2013, 07:28 AM   #3
RandyTech
Member
 
Registered: Oct 2010
Posts: 62

Original Poster
Rep: Reputation: 3
Hi pan64 and thanks much for your reply.
This is running in a Centos 4.x machine using /bin/bash

regardless... any idea on syntax, how to get the results into a variable?
 
Old 01-25-2013, 07:29 AM   #4
konsolebox
Senior Member
 
Registered: Oct 2005
Distribution: Gentoo, Slackware, LFS
Posts: 2,248
Blog Entries: 8

Rep: Reputation: 235Reputation: 235Reputation: 235
It's not even a one-liner IMO. It's just a condensed set of multiple instructions.

Anyway I think you could change that to:
Code:
MyVar=$(find /etc/sysconfig/ -type d | while read dir; do echo "$dir:$(find "$dir" -type f | wc -l)"; done | sort -k2 -t: -n | head -n1 | cut -f1 -d:)
Certainly that could be simplified but it depends on what you really want to do noting /etc/sysconfig seems specific.
 
1 members found this post helpful.
Old 01-25-2013, 07:30 AM   #5
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,850

Rep: Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309Reputation: 7309
instead, I would use a simple perl script.
 
Old 01-25-2013, 07:45 AM   #6
RandyTech
Member
 
Registered: Oct 2010
Posts: 62

Original Poster
Rep: Reputation: 3
bash script is a big stretch for me, but mostly just same as linux line command so I get by. I know nothing about perl.
 
Old 01-25-2013, 08:05 AM   #7
RandyTech
Member
 
Registered: Oct 2010
Posts: 62

Original Poster
Rep: Reputation: 3
Hi konsolebox and thanks many times over for your example!!!
Quote:
Originally Posted by konsolebox View Post
It's not even a one-liner IMO. It's just a condensed set of multiple instructions.

Anyway I think you could change that to:
Code:
MyVar=$(find /etc/sysconfig/ -type d | while read dir; do echo "$dir:$(find "$dir" -type f | wc -l)"; done | sort -k2 -t: -n | head -n1 | cut -f1 -d:)
Certainly that could be simplified but it depends on what you really want to do noting /etc/sysconfig seems specific.
With that I was able to spot possible syntax errors in the original one-liner and get it working as line command too:
Code:
find /etc/sysconfig/ -type d | while read dir; do echo "$dir:$(find "$dir" -type f | wc -l)" ; done | sort -k2 -t ':' -n |head -n 1
And with that, ultimately get the original one-liner working inside my script file to pass results into the variable:
Code:
MyVar=$(find /etc/sysconfig/ -type d | while read dir; do echo "$dir:$(find "$dir" -type f | wc -l)" ; done | sort -k2 -t ':' -n |head -n 1)
Believe me, I tried putting the whole line inside $(code) but no joy there. I tried $((code)) and ($(code)), and even replace with variatins using square brackets.

Any, marking this issue [SOLVED] and thanks again for your help!!
 
Old 01-25-2013, 08:16 AM   #8
RandyTech
Member
 
Registered: Oct 2010
Posts: 62

Original Poster
Rep: Reputation: 3
Quote:
Originally Posted by konsolebox View Post
It's not even a one-liner IMO. It's just a condensed set of multiple instructions.
Its a grey area I guess, and I get what you are saying so I have to agree in some part. If it can legitimately go onto a single command line at the system prompt and complete a task (simple or complex) without further user action then I have to classify that as a one-liner, even if it is composed of multiple instructions.
 
Old 01-25-2013, 08:22 AM   #9
RandyTech
Member
 
Registered: Oct 2010
Posts: 62

Original Poster
Rep: Reputation: 3
Quote:
Originally Posted by konsolebox View Post
... it depends on what you really want to do noting /etc/sysconfig seems specific.
In case you are curious, I knew that path was generic to all *nux systems with multiple sub-directories, so safe to use it in my sample code and expect anyone would get something more illustrative than file not found error.
 
Old 01-25-2013, 09:36 AM   #10
konsolebox
Senior Member
 
Registered: Oct 2005
Distribution: Gentoo, Slackware, LFS
Posts: 2,248
Blog Entries: 8

Rep: Reputation: 235Reputation: 235Reputation: 235
I see. Anyhow welcome
 
Old 01-27-2013, 12:29 PM   #11
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
1) When you have complex commands it might help to set them up in a function first, and capture the results of that.

2) $(..) is highly recommended over `..`. It's easier to read and nests better. As far as I'm concerned, nobody using a modern shell should ever need to touch the backtick key.

3) In bash, process substitution is usually preferred over piping something into a loop, as it avoids the variable scoping issue.

4) When operating on file lists produced by find, you should generally use the -print0 null separator option (and the corresponding input options in the receiving commands).

4) Also, for commands that produce multiple lines of output, you should usually consider storing them in an array instead. The new mapfile built-in makes this easy, although it doesn't work with null separators. That would require another read loop.

5) The second find in the sample code could be replaced with a simple subloop (run in a subshell to avoid having to reset the variables).


Code:
dircount() {

    local dname fname fnum
    while IFS='' read -r -d '' dname; do
        (
          cd "$dname"
	  for fname in * ; do
	      [[ -f "$fname" ]] && (( fnum++ ))
          done
	  printf '%d : %s\n' "$fnum" "$dname"
        )
    done < <( find "$1" -type d -print0 ) | sort -k1,1n

}

mapfile -t myArray < <( dircount /etc/sysconfig )

echo "${myArray[0]}"             #show the smallest entry
echo "${myArray[-1]}"            #show the largest entry
printf '%s\n' "${myArray[@]}"    #list all entries, one per line

It's a bit more code, but I think it's cleaner overall. If I was really up to it I could've also replaced the sort command with a sorting loop as well, but why bother reinventing the wheel?
 
Old 01-27-2013, 04:35 PM   #12
RandyTech
Member
 
Registered: Oct 2010
Posts: 62

Original Poster
Rep: Reputation: 3
Thumbs up

>>> ENTER THE MASTER >>>
Quote:
Originally Posted by David the H. View Post
1) ... might help to set them up in a function first ...
Wow David -- They don't label you "guru" for nothing -- Thanks!!
You lost me starting with the first comment and stayed pretty consistent that way to the end. I might have a chance spotting a syntax issue, and I can usually break these so called one-liners down to individual command lines to help figure them out (sometimes not), but total reconstruction with alternative command set and and and ... whaaaah. You are sooo over my head.

That's ok though. I appreciate the effort behind the added commentary even if I don't understand. Mostly because I know my subject line should be luring enough to bring users more advanced than myself into the thread to feast on your illustrious post. Well, that is, hopefully they don't get thrown by the "go use perl instead" comment and lose all interest.

Oh, I did understand most the comments tucked away there in your link regarding $(...) so that should come in handy to know. Really like the way you took time to provide topical comments and links. Thanks again!! Thumbs up
 
Old 01-27-2013, 05:01 PM   #13
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
Heheh. Sorry if I threw too much at you at once. Just take it slow and work your way through it at your own pace. Read the links I gave. It really isn't that difficult once you start to become familiar with it.

If you haven't seen it yet, take some time to read through the http://mywiki.wooledge.org/BashGuide from the same site. It should give you a good grounding in all the basics of shell syntax.

And if you have any specific questions, just ask!
 
  


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] Problem in exporting variable from bash script to expect script uk.engr Linux - Newbie 3 06-14-2012 01:57 AM
bash script path issue - how to pass a path as a string to a variable PiNPOiNT Programming 5 04-17-2009 05:48 PM
Problem with bash script - variable name within variable name steven.c.banks Linux - Newbie 3 03-10-2009 03:08 AM
LXer: Bash One-Liner Script To Produce Somewhat-Fancy Output Of Who's On Your Linux O LXer Syndicated Linux News 0 11-19-2008 01:40 AM
How to pass a c variable to a bash script? daYz Programming 3 09-28-2007 08:30 AM

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

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