[Novalug] Fill in the blanks?

James Ewing Cottrell 3rd JECottrell3 at Comcast.NET
Fri Mar 16 17:18:26 EDT 2012


Glad to be of service. I should also add that ls always assumes -1 if 
STDOUT is not a TTY. However, if you don't care about sorting, "ls -f" 
will simply output the entries in whatever order they are in the directory.

Yes, basename is available everywhere, but it needs to be invoked as a 
separate program. Better to use the internal Parameter Selection 
mechanisms. BTW, these are not bash-isms; they are POSIX, so sh, ksh, 
bash, and possibly zsh will work. You shouldn't be using tcsh.

Quick tutorial on Parameter Selection: consider that # means left and % 
means right (mnemonic: relative to the $ sign).

${x#string} removes string from the left of x, ${x%string} removes it 
from the right. String uses filename matching, where ? is one character, 
and * is many. Presumably, [y-z] character classes work too, but I never 
use them. Doubling the # or % makes the matching greedy, so if file is 
/a/b/c, the ${file#/*} gives /b/c and ${file##/*} gives /c and 
${file##*/} gives c.

Note that * does not match /.

I would also urge you not to quote arguments unless needed. Quoting 
rules are simple and worth learning. Echo echoes spaces between 
arguments, so "echo basename: ${fn%.*}" is fine. Yours gets two spaces.

I mentioned the max command line chars limitation for completeness, but 
it's totally OK to assume there is none in most cases...a million chars 
is pretty generous.

However, ls | while read or ls | xargs can run in parallel, each process 
on a separate CPU. Consider the command

find / -type f | while read file; do wc $file; done

Which makes a decent "is the disk OK?" benchmark versus: for file in 
$(find / -type f); do wc $file; done

Which would read the entire disk first (also: way more than 1M chars). 
Even better...pipe to xargs wc

JIM

On 3/16/2012 3:24 PM, daniel wrote:
> I like what I'm learning here.  Thanks to all for your input and if
> there's more, I'm listening!
>
> What I am taking away from this is many things, but the limitations of
> smaller shells is an important point.  If I were doing this on an
> Android or something limitations on memory are certainly a concern as is
> processing load.
>
> I wanted all of this to be run from the command line, of course as I
> don't want to write a whole program... just to make a quick and dirty
> command line to do the thing I wanted to do and be done with it.
>
> However, I would also like to expand the discussion to include things
> like renaming files in large amounts... something we all need to do from
> time to time no?
>
> Anyway, as I play with this more, I came up with this:
>
>
> ls -1 *.* | while read fn; do echo "processing " $fn ; echo "basename: "
> ${fn%.*}  ; done
>
> I use "ls -1 *.*" followed by a pipe to deal with string limitations
> that may be exceeded by a wildcard.  Using read to handle each line as
> it comes in should relieve that problem.  I like the ${fn%.*} thing
> though I haven't looked into what it means, exactly and I don't know
> what shells support this notation and what shells do not.  It would be a
> useful thing to know, but basename seems to be included everywhere even
> if it's considered obsolete.
>
>
>
> On 03/16/2012 03:57 PM, James Ewing Cottrell 3rd wrote:
>> On 3/16/2012 7:29 AM, William Sutton wrote:
>>> Chiming in later, but the ls -1 part is probably unnecessary.  I routinely
>>> use
>>>
>>> for f in *; do something; done;
>>>
>>> in bash.
>> The only time this makes a difference is on old shells. Command lines
>> are limited to some implementation-specific maximum length, and will
>> generate errors after that. I believe that it's in the millions of
>> characters now, but it used to be 10K (or even 1K) twenty years ago, so
>> that statements like (cd /tmp; rm -f *) would often fail. You needed to
>> do something like (cd /tmp; ls | xargs rm -f) to get things to work when
>> many files were involved.
>>> OTOH, I learned a few things reading this too, like basename :-)
>> One of my points was that basename is essentially Obsolete. I haven't
>> used them in a decade or so.
>>> William Sutton
>> JIM
>>
>> _______________________________________________
>> Novalug mailing list
>> Novalug at calypso.tux.org
>> http://calypso.tux.org/mailman/listinfo/novalug
> _______________________________________________
> Novalug mailing list
> Novalug at calypso.tux.org
> http://calypso.tux.org/mailman/listinfo/novalug
>



More information about the Novalug mailing list