Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

HOW2 find VT of an app. ?

55 views
Skip to first unread message

no.to...@gmail.com

unread,
Oct 31, 2012, 5:54:51 PM10/31/12
to
ls -l /proc | wc -l == gives you the number of <dir-entries>
If you then open a new VT, this number increases by 2.
And `ls -t` will show this sub-dir.

lsof | grep <app> for 3 different apps shows: ...
lsof | grep snow == 11 /dev/pts8 <-- @ WS5, VT1 & only
lsof | grep links == 10 /dev/pts7 <-- @ ?
lsof | grep wily == 8 /dev/pts5 <-- @ WS2, VT4

Apparently these <pairs>:8,5 don't relate to the VT.

Surely some other users often want to find which
WS,VT has got a certain utility?

== TIA.

Chris F.A. Johnson

unread,
Oct 31, 2012, 6:26:44 PM10/31/12
to
On 2012-10-31, no.to...@gmail.com wrote:
> ls -l /proc | wc -l == gives you the number of <dir-entries>

Why do you use the -l option?

Why do you use ls at all?

printf "%s\n" /proc/* | wc -l

--
Chris F.A. Johnson, <http://cfajohnson.com>
Author:
Pro Bash Programming: Scripting the GNU/Linux Shell (2009, Apress)
Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)

Richard Kettlewell

unread,
Oct 31, 2012, 6:50:35 PM10/31/12
to
The controlling terminal for a process can be found in /proc/PID/stat;
see 'man 5 proc' for details.

lsof is the wrong tool for retrieving this information. It is, however,
documented, if you're having trouble interpreting its output.

--
http://www.greenend.org.uk/rjk/

Floyd L. Davidson

unread,
Oct 31, 2012, 6:57:37 PM10/31/12
to
"Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>On 2012-10-31, no.to...@gmail.com wrote:
>> ls -l /proc | wc -l == gives you the number of <dir-entries>
>
> Why do you use the -l option?
>
> Why do you use ls at all?
>
>printf "%s\n" /proc/* | wc -l

I actually use 'll *jpg | wc -l' relatively often, usually
after uploading images from a camera because it gives a quick
count of how many there are in the directory.

Obviously 'll' is an alias for '/bin/ls -l', and the reason
for using that instead of just 'ls' is that 'ls' is an
alias for '/bin/ls -xF' and will not output one file per
line to a pipe.

Ultimately, 'll dir | wc -l' is the shortest command line
to type, being several characters less "work" than using
the printf equivalent.

Hmmm... given the frequency of use, maybe that should be
aliased to something like 'lc'.

--
Floyd L. Davidson http://www.apaflo.com/floyd_davidson
Ukpeagvik (Barrow, Alaska) fl...@apaflo.com

Chris F.A. Johnson

unread,
Oct 31, 2012, 8:21:59 PM10/31/12
to
On 2012-10-31, Floyd L. Davidson wrote:
> "Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>>On 2012-10-31, no.to...@gmail.com wrote:
>>> ls -l /proc | wc -l == gives you the number of <dir-entries>
>>
>> Why do you use the -l option?
>>
>> Why do you use ls at all?
>>
>>printf "%s\n" /proc/* | wc -l
>
> I actually use 'll *jpg | wc -l' relatively often, usually
> after uploading images from a camera because it gives a quick
> count of how many there are in the directory.
>
> Obviously 'll' is an alias for '/bin/ls -l', and the reason
> for using that instead of just 'ls' is that 'ls' is an
> alias for '/bin/ls -xF' and will not output one file per
> line to a pipe.

If the output is not going to a terminal, ls will print the files
one to a line. There's no need for options (which slow it down).

> Ultimately, 'll dir | wc -l' is the shortest command line
> to type, being several characters less "work" than using
> the printf equivalent.

I have a function defined which prints its argument one to a
line:

pr1()
{
printf "%s\n" "$@"
}

So I would actually use:

pr1 /proc/* | wc -l

terryc

unread,
Oct 31, 2012, 8:41:04 PM10/31/12
to
On 01/11/12 09:57, Floyd L. Davidson wrote:

> Hmmm... given the frequency of use, maybe that should be
> aliased to something like 'lc'.

The only problem with doing something like that is when you obtain a
"new" computer, it becomes a whole pile of "oh damm, what was that
sequence again" as you try to remember and set up all the shortcuts you
have previously set up and been using for years.



Chris F.A. Johnson

unread,
Oct 31, 2012, 8:49:27 PM10/31/12
to
I copy all my scripts (and a lot else) to the new computer. My working
environment remains the same.

Floyd L. Davidson

unread,
Oct 31, 2012, 9:48:57 PM10/31/12
to
"Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>On 2012-10-31, Floyd L. Davidson wrote:
>> "Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>>>On 2012-10-31, no.to...@gmail.com wrote:
>>>> ls -l /proc | wc -l == gives you the number of <dir-entries>
>>>
>>> Why do you use the -l option?
>>>
>>> Why do you use ls at all?
>>>
>>>printf "%s\n" /proc/* | wc -l
>>
>> I actually use 'll *jpg | wc -l' relatively often, usually
>> after uploading images from a camera because it gives a quick
>> count of how many there are in the directory.
>>
>> Obviously 'll' is an alias for '/bin/ls -l', and the reason
>> for using that instead of just 'ls' is that 'ls' is an
>> alias for '/bin/ls -xF' and will not output one file per
>> line to a pipe.
>
> If the output is not going to a terminal, ls will print the files
> one to a line. There's no need for options (which slow it down).

The alias to "/bin/ls -xF", even when not going to a
terminal, prints formatted lines rather than one to a
line. That appears to be an artifact of the -x option.
The point is that the alias is there for command line
use, and the options "which slow it down" are still
important, while slow is insignificant.

But when piped to wc, that does not work, while the ll
alias with the long form does work. (Note too that "ls -l"
without an argument, such as "ls -l ." will produce one
extra line of output.)

>> Ultimately, 'll dir | wc -l' is the shortest command line
>> to type, being several characters less "work" than using
>> the printf equivalent.
>
> I have a function defined which prints its argument one to a
> line:
>
>pr1()
>{
> printf "%s\n" "$@"
>}
>
> So I would actually use:
>
>pr1 /proc/* | wc -l

Pretty much the same effort, but yours has the distinct
advantage (okay, an insignificant difference today) of
using the bash builtin printf as opposed to my command
invoking another process unnecessarily.

I did decide to work on a function (rather than an
alias), and now have this in my .bashrc file:

function lc {
printf "Count: %s\n" $(printf "%s\n" ${@:-*} | wc -l) ;
}

Another way to do that is:

function lc {
echo -n "Count: " ; printf "%s\n" ${@:-*} | wc -l ;
}


It's specialized for counting how many of any given type
of file exists in a directory, and fills a very
common need for my use.

Thanks for the discussion and prompting me to give it
some new thought!

Floyd L. Davidson

unread,
Oct 31, 2012, 10:01:43 PM10/31/12
to
I'm like Chris... I've been using essentially the same
environment for literally decades, with only minor
incremental changes over any span of a few years in
recent times. But more important actually is the use of
a network with multiple computers, so finding what I did
before is just a matter of looking, not remembering.

With a new computer or an upgrade to the OS the top of
the priority list is copying all of the dot files from
my home directory into place, and then getting XEmacs
and gnuclient up an running.

Chris F.A. Johnson

unread,
Oct 31, 2012, 10:43:05 PM10/31/12
to
On 2012-11-01, Floyd L. Davidson wrote:
...
> Pretty much the same effort, but yours has the distinct
> advantage (okay, an insignificant difference today) of
> using the bash builtin printf as opposed to my command
> invoking another process unnecessarily.

The difference is far from insignificant. Calling an external command
takes many times longer than using a builtin command:

q=( {1..1000} )

time for n in "${q[@]}"
do
echo $n
done > /dev/null

real 0m0.009s
user 0m0.009s
sys 0m0.000s


time for n in "${q[@]}"
do
/bin/echo $n
done > /dev/null

real 0m0.984s
user 0m0.050s
sys 0m0.269s

> I did decide to work on a function (rather than an
> alias), and now have this in my .bashrc file:
>
> function lc {
> printf "Count: %s\n" $(printf "%s\n" ${@:-*} | wc -l) ;
> }
>
> Another way to do that is:
>
> function lc {
> echo -n "Count: " ; printf "%s\n" ${@:-*} | wc -l ;
> }

You will find the latter much faster than the former;
command substitution is far slower than the alternative.

I'd do it this way, since the -n option to echo is not portable
(and you only need one statement):

function lc {
printf "Count: %s\n" ${@:-*} | wc -l ;

Chris F.A. Johnson

unread,
Oct 31, 2012, 11:27:10 PM10/31/12
to
Sorry, you do need two statements.

That should be:

lc() {
printf "Count: "
printf "%s\n" ${@:-*} | wc -l ;
}

But ${@:-*} will fail if any filenames contain whitespace
(since $@ is not quoted). Try this:

lc()
{
printf "Count: "
[ $# -eq 0 ] && set -- *
printf "%s\n" "$@" | wc -l ;

Michael Black

unread,
Oct 31, 2012, 11:58:04 PM10/31/12
to
That's why you should keep a log, from the moment of first install.

This lets you keep track of what you've added (so the next install you can
add the extras very fast), when you've added hardware, how to use a
specific piece of software (so you get the flags set right). I suppose
later one could organize it, even set some of it up as a custom man page,
but the reality is I can remember a lot, just not the fine details, so a
search of the file shows what I need. I've even tried to do something,
failed, but have a record of what I tried, so the next time I feel like
tackling something, I can start where I left off.

As you start, that's the time of lots of entries. The more you use Linux,
the less there is to enter, since you've already figured out the sorts of
things you yourself need to do.

If you don't want to do that, you can often get information from the date
stamp on a file. Sort the /etc directory by date, and you can easily find
the files that were "tampered with" after the install, things that you've
customized. Sort the various bin directories the same way, and you can
find the things have been added after install, really useful when you've
added things that don't come from the distribution's depository.

Then of course, don't erase the old before you've settled into the new.
At the very least, keep a copy of /home handy and /etc at least until
you've decided you've remembered all the customizing you've done. I don't
know if it's changed, but I thought I lost something the first time I
moved to a newer release, some config hidden away in an obscure place.

Another trick is that some software (and I don't know if it holds for
every piece) doesn't care about the sequence of the configure file. So
just put your own customizing at the end of the configure file, and it's
so much easier the next time to retrieve that, rather than going through
the old config files to see what you changed. At the very least, mark the
changes with a comment, use something distinctive so you can easily find
them with a search.

I just installed a new release of my favorite distribution, on a "new"
computer. I haven't got it all set up the way i want it, but this is the
fastest changeover I've done in 11 years. It helped that I was going to a
"new" computer so I could run the old at the same time, but since I've
moved to new releases a few times, I've got it down pat. What I had to
fuss over was the new things, suddenly no longer with dial-up (I pretty
much kept the files that I used first in 2001 for that, just shifting them
to the new install), but having to figure out wifi. But since I've kept
records of that, it will be easy the next time.

The first time I installed Linux, I didn't use partitions, it was "only" a
2gig hard drive back then. And it didn't take long before I realized that
was a mistake. I couldn't try other distributions (which at the time
seemed like an interesting idea) without wiping out what I had already
been working on. But once I got a larger drive, I'd install in a new
partition, and dual boot, so I could fall back to the old if I missed
something. It doesn't work out that well, I found I just stayed with the
old distribution until I actually made a firm commitment to the new
release, but it is handy. Then I could reuse that old partition for the
next release.

And since I do keep /home in a separate partition, I actually don't mount
the old home until I've played with the new release a bit, just keep
everything safe for a bit. Then I manually make the changes that cause
the /home partition to mount on boot. Since I moved to another computer
this time, I just copied /etc and /home to a usb flash drive, which makes
things a lot simpler than haning the old hard drive off the side of the
case until I've sucked all I want out of it.

One of the things to be aware of is that some people are actualy system
administrators, so they can pull things off the otp of their head since
they are constantly keeping a release up to date, constantly having to
deal with other people's problems. That's why they can instantly provide
an answer. For the rest of us, keeping a detailed log means we can keep
details handy without hving to remember it all. Sometimes figuring out
the exact flags to do something like record an ISO to a blank CD takes a
bit of work, but once youv'e got it, no sense in having to remember or
figure it out again the next time, you've got it written down.

Michael

Floyd L. Davidson

unread,
Nov 1, 2012, 2:22:18 AM11/1/12
to
"Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>On 2012-11-01, Floyd L. Davidson wrote:
>...
>> Pretty much the same effort, but yours has the distinct
>> advantage (okay, an insignificant difference today) of
>> using the bash builtin printf as opposed to my command
>> invoking another process unnecessarily.
>
> The difference is far from insignificant. Calling an external command
> takes many times longer than using a builtin command:

Sheesh, Chris... speed, for an interactive command line invocation,
is of virtually no significance at all.

...

>> function lc {
>> printf "Count: %s\n" $(printf "%s\n" ${@:-*} | wc -l) ;
>> }
>>
>> Another way to do that is:
>>
>> function lc {
>> echo -n "Count: " ; printf "%s\n" ${@:-*} | wc -l ;
>> }
>
> You will find the latter much faster than the former;
> command substitution is far slower than the alternative.

Speed makes no difference, but since both use identical
command substitution they would be equally "slow".

> I'd do it this way, since the -n option to echo is not portable
> (and you only need one statement):
>
>function lc {
> printf "Count: %s\n" ${@:-*} | wc -l ;
>}

Your function doesn't do the same thing. There is no point in using
that control string for printf if it is deleted by piping it to wc.

The intention is to have output that tells the user what it is:

>lc *.jpg
Count: 14

Floyd L. Davidson

unread,
Nov 1, 2012, 2:33:31 AM11/1/12
to
"Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>> function lc {
>> printf "Count: %s\n" ${@:-*} | wc -l ;
>> }
>
> Sorry, you do need two statements.
>
> That should be:
>
>lc() {
> printf "Count: "
> printf "%s\n" ${@:-*} | wc -l ;
>}
>
> But ${@:-*} will fail if any filenames contain whitespace
> (since $@ is not quoted). Try this:
>
>lc()
>{
> printf "Count: "
> [ $# -eq 0 ] && set -- *
> printf "%s\n" "$@" | wc -l ;
>}

Whoa, that one is better!

I was aware of the quoting problem for spaces, but
hadn't spent any time at all thinking about what to do.
It's not terribly important as my image file names never
have spaces, but still I appreciate that a more robust
and generic command is better! (And I doubt that I'd
ever have come up with that.)

Floyd L. Davidson

unread,
Nov 1, 2012, 4:20:05 AM11/1/12
to
fl...@apaflo.com (Floyd L. Davidson) wrote:
>>lc()
>>{
>> printf "Count: "
>> [ $# -eq 0 ] && set -- *
>> printf "%s\n" "$@" | wc -l ;
>>}
>
>Whoa, that one is better!

Opps, none of them were tested well enough. All of
these functions using parameter substitution fail if the
given argument expands to an empty set of files, the
output says the count is 1. For example, if the
directory is empty, and no arg is given, '*' will be
substituted and 'printf "%s\n" "$@" will be 'printf
"%s\n" "*"' and will print one line with a single '*' on
it, which wc -l will correctly count a 1.

At this point I don't see any worthwhile way of avoiding
/bin/ls. Here are three different ways to do it with
a call to /bin/ls:

function lc {
[ "$#" -eq 0 ] && echo -n "Count: " && /bin/ls -l * 2>/dev/null | wc -l && return
echo -n "Count: " && /bin/ls -l "${@}" 2>/dev/null | wc -l
}

function lc {
[ "${#}" -eq 0 ] && {
echo -n "Count: "
/bin/ls -l * 2>/dev/null | wc -l
return
}
echo -n "Count: "
/bin/ls -l "${@}" 2>/dev/null | wc -l
}

function lc {
if [ "${#}" -eq 0 ] ; then
echo -n "Count: "
/bin/ls -l * 2>/dev/null | wc -l
else
echo -n "Count: "
/bin/ls -l "${@}" 2>/dev/null | wc -l
fi

Kees Theunissen

unread,
Nov 1, 2012, 5:07:50 AM11/1/12
to
Still not tested well enough!
The command /bin/ls -l * will list the contents of subdirectories.
I think that /bin/ls -ld * does what you want. (untested)

You might want to use /bin/ls -1d * with option -1 (number one)
instead of -l (lowercase L). That should be faster as it gives a single
column output without the need to "stat" each item.


Chris F.A. Johnson

unread,
Nov 1, 2012, 5:14:27 AM11/1/12
to
On 2012-11-01, Floyd L. Davidson wrote:
> fl...@apaflo.com (Floyd L. Davidson) wrote:
>>>lc()
>>>{
>>> printf "Count: "
>>> [ $# -eq 0 ] && set -- *
>>> printf "%s\n" "$@" | wc -l ;
>>>}
>>
>>Whoa, that one is better!
>
> Opps, none of them were tested well enough. All of
> these functions using parameter substitution fail if the
> given argument expands to an empty set of files, the
> output says the count is 1. For example, if the
> directory is empty, and no arg is given, '*' will be
> substituted and 'printf "%s\n" "$@" will be 'printf
> "%s\n" "*"' and will print one line with a single '*' on
> it, which wc -l will correctly count a 1.
>
> At this point I don't see any worthwhile way of avoiding
> /bin/ls.

You can avoid wc as well as ls (assuming bash):

lc()
{
printf "Count: "
shopt -s nullglob
case $* in
\* | "" ) set -- * ;;
*) set -- "$@" ;;
esac
printf "%d\n" "$#"

Floyd L. Davidson

unread,
Nov 1, 2012, 6:19:06 AM11/1/12
to
Kees Theunissen <theu...@rijnh.nl> wrote:
>Floyd L. Davidson wrote:
>
>Still not tested well enough!
>The command /bin/ls -l * will list the contents of subdirectories.
>I think that /bin/ls -ld * does what you want. (untested)
>
>You might want to use /bin/ls -1d * with option -1 (number one)
>instead of -l (lowercase L). That should be faster as it gives a single
>column output without the need to "stat" each item.

Looks good!

Floyd L. Davidson

unread,
Nov 1, 2012, 6:59:32 AM11/1/12
to
"Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>> At this point I don't see any worthwhile way of avoiding
>> /bin/ls.
>
> You can avoid wc as well as ls (assuming bash):
>
>lc()
>{
> printf "Count: "
> shopt -s nullglob
> case $* in
> \* | "" ) set -- * ;;
> *) set -- "$@" ;;
> esac
> printf "%d\n" "$#"
>}

Same problem with the parameter substitution though, with the
result that it returns 1 for an empty directory.

This is not exactly elegant, but it works in directories
with sub directories and in empty directories, with or
without any command line argument or wildcards.

function lc {
echo -n "Count: "
if [ "${#}" -eq 0 ] ; then
/bin/ls -1d * 2>/dev/null | grep -v '^\.$' | wc -l
else
/bin/ls -1d "${@}" 2>/dev/null | wc -l

Chris F.A. Johnson

unread,
Nov 1, 2012, 7:09:04 AM11/1/12
to
On 2012-11-01, Floyd L. Davidson wrote:
> "Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>>> At this point I don't see any worthwhile way of avoiding
>>> /bin/ls.
>>
>> You can avoid wc as well as ls (assuming bash):
>>
>>lc()
>>{
>> printf "Count: "
>> shopt -s nullglob
>> case $* in
>> \* | "" ) set -- * ;;
>> *) set -- "$@" ;;
>> esac
>> printf "%d\n" "$#"
>>}
>
> Same problem with the parameter substitution though, with the
> result that it returns 1 for an empty directory.

It returns 0 in an empty directory
(that's what 'shopt -s nullglob' is for).

Floyd L. Davidson

unread,
Nov 1, 2012, 8:26:06 AM11/1/12
to
"Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>On 2012-11-01, Floyd L. Davidson wrote:
>> "Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>>>> At this point I don't see any worthwhile way of avoiding
>>>> /bin/ls.
>>>
>>> You can avoid wc as well as ls (assuming bash):
>>>
>>>lc()
>>>{
>>> printf "Count: "
>>> shopt -s nullglob
>>> case $* in
>>> \* | "" ) set -- * ;;
>>> *) set -- "$@" ;;
>>> esac
>>> printf "%d\n" "$#"
>>>}
>>
>> Same problem with the parameter substitution though, with the
>> result that it returns 1 for an empty directory.
>
> It returns 0 in an empty directory
> (that's what 'shopt -s nullglob' is for).

It does work as expected. I must not have had it defined when I
thought it was before.

This one looks by far better than the methods I came up with.

Joe Beanfish

unread,
Nov 1, 2012, 9:12:18 AM11/1/12
to
Does this help?

ps -o pid,user,tty,cmd -C snow

Chris F.A. Johnson

unread,
Nov 1, 2012, 9:14:16 AM11/1/12
to
On 2012-11-01, Floyd L. Davidson wrote:
> "Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>>On 2012-11-01, Floyd L. Davidson wrote:
>>> "Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>>>>> At this point I don't see any worthwhile way of avoiding
>>>>> /bin/ls.
>>>>
>>>> You can avoid wc as well as ls (assuming bash):
>>>>
>>>>lc()
>>>>{
>>>> printf "Count: "
>>>> shopt -s nullglob
>>>> case $* in
>>>> \* | "" ) set -- * ;;
>>>> *) set -- "$@" ;;
>>>> esac
>>>> printf "%d\n" "$#"
>>>>}
>>>
>>> Same problem with the parameter substitution though, with the
>>> result that it returns 1 for an empty directory.
>>
>> It returns 0 in an empty directory
>> (that's what 'shopt -s nullglob' is for).
>
> It does work as expected. I must not have had it defined when I
> thought it was before.
>
> This one looks by far better than the methods I came up with.

Strictly speaking, one should check the status of nullglob and restore it on
exit:

lc()
{
local ng
shopt -q nullglob || ng=off
shopt -s nullglob

case $* in
\* | "" ) set -- * ;;
*) set -- "$@" ;;
esac

printf "Count: %d\n" "$#"

[ "$ng" = off ] && shopt -u nullglob

Wayne

unread,
Nov 1, 2012, 12:33:34 PM11/1/12
to
On 11/1/2012 9:14 AM, Chris F.A. Johnson wrote:
>
> lc()
> {
> local ng
> shopt -q nullglob || ng=off
> shopt -s nullglob
>
> case $* in
> \* | "" ) set -- * ;;
> *) set -- "$@" ;;
> esac
>
> printf "Count: %d\n" "$#"
>
> [ "$ng" = off ] && shopt -u nullglob
> }
>

This doesn't seem to work as I expected:

$ lc *zzzqqqzzz # should return zero
Count: 1

$ shopt -s nullglob

$ set -- zzz*aaaaaa

$ echo $# # should show zero
0

$ lc zzz*aaaaaa # note that nullglob is still set
Count: 17

$ bash --version
GNU bash, version 4.2.28(1)-release (i386-redhat-linux-gnu)

Given how unlikely it is that this function will be invoked in
a loop in a situation where performance matters, I'm thinking
Kees solution (using ls and wc) might be more correct.

--
Wayne

Robert Heller

unread,
Nov 1, 2012, 3:32:26 PM11/1/12
to
It is also cross-platform, including cross-shell...

>

--
Robert Heller -- 978-544-6933 / hel...@deepsoft.com
Deepwoods Software -- http://www.deepsoft.com/
() ascii ribbon campaign -- against html e-mail
/\ www.asciiribbon.org -- against proprietary attachments



Chris F.A. Johnson

unread,
Nov 3, 2012, 12:29:19 AM11/3/12
to
On 2012-11-01, Wayne wrote:
> On 11/1/2012 9:14 AM, Chris F.A. Johnson wrote:
>>
>> lc()
>> {
>> local ng
>> shopt -q nullglob || ng=off
>> shopt -s nullglob
>>
>> case $* in
>> \* | "" ) set -- * ;;
>> *) set -- "$@" ;;
>> esac
>>
>> printf "Count: %d\n" "$#"
>>
>> [ "$ng" = off ] && shopt -u nullglob
>> }
>>
>
> This doesn't seem to work as I expected:
>
> $ lc *zzzqqqzzz # should return zero
> Count: 1

That's what happens when the specs are not clearly laid out.

lc()
{
local ng= format=${lc_format-"Count: %d\n"}
[ -n "$lc_var" ] && format=%d
case $* in
*\** | *\[*\]* ) shopt -q nullglob || ng=off
shopt -s nullglob
set -- $*
;;
"" ) shopt -q nullglob || ng=off
shopt -s nullglob
set -- *
;;
esac
printf ${lc_var:+-v "$lc_var"} "${format:-%d\n}" "$#"
[ "$ng" = off ] && shopt -u nullglob
}

> $ shopt -s nullglob
>
> $ set -- zzz*aaaaaa
>
> $ echo $# # should show zero
> 0
>
> $ lc zzz*aaaaaa # note that nullglob is still set
> Count: 17
>
> $ bash --version
> GNU bash, version 4.2.28(1)-release (i386-redhat-linux-gnu)
>
> Given how unlikely it is that this function will be invoked in
> a loop in a situation where performance matters,

Why not? In fact, I have used it in a loop. I wanted to know how
many files were in each subdirectory in the current directory.

for d in */
do
lc "$d"/*
done

> I'm thinking
> Kees solution (using ls and wc) might be more correct.

Only if performance doesn't matter.

The trouble with writing inefficient code for use at the command
line is that is often gets incorporated into script where it does
matter.

Chris F.A. Johnson

unread,
Nov 3, 2012, 12:22:12 AM11/3/12
to
On 2012-11-01, Floyd L. Davidson wrote:
> "Chris F.A. Johnson" <cfajo...@gmail.com> wrote:
>>On 2012-11-01, Floyd L. Davidson wrote:
>>...
>>> Pretty much the same effort, but yours has the distinct
>>> advantage (okay, an insignificant difference today) of
>>> using the bash builtin printf as opposed to my command
>>> invoking another process unnecessarily.
>>
>> The difference is far from insignificant. Calling an external command
>> takes many times longer than using a builtin command:
>
> Sheesh, Chris... speed, for an interactive command line invocation,
> is of virtually no significance at all.

Nonsense!!!!!

It is even more important than in a compiled command.

A well-written script should appear as snappy as a utility written
in C.

> ...
>
>>> function lc {
>>> printf "Count: %s\n" $(printf "%s\n" ${@:-*} | wc -l) ;
>>> }
>>>
>>> Another way to do that is:
>>>
>>> function lc {
>>> echo -n "Count: " ; printf "%s\n" ${@:-*} | wc -l ;
>>> }
>>
>> You will find the latter much faster than the former;
>> command substitution is far slower than the alternative.
>
> Speed makes no difference, but since both use identical
> command substitution they would be equally "slow".

The second one doesn't use command substitution, which is almost as
slow (in bash) as calling an external command.

>> I'd do it this way, since the -n option to echo is not portable
>> (and you only need one statement):
>>
>>function lc {
>> printf "Count: %s\n" ${@:-*} | wc -l ;
>>}
>
> Your function doesn't do the same thing. There is no point in using
> that control string for printf if it is deleted by piping it to wc.

True; fixed in a later post.

> The intention is to have output that tells the user what it is:
>
> >lc *.jpg
> Count: 14

--
0 new messages