The macosxhints Forums

The macosxhints Forums (http://hintsforums.macworld.com/index.php)
-   UNIX - General (http://hintsforums.macworld.com/forumdisplay.php?f=16)
-   -   Ditto Within a For Loop (http://hintsforums.macworld.com/showthread.php?t=53579)

Hal Itosis 03-29-2006 12:25 AM

Quote:

Originally Posted by UncleJohn
Code:

G5:~$ ls -1t | head -2 | xargs -I % ls "%"
File One
File Two

The difference is that -I operates on an entire line of input
while -J will split on white space.

Brilliant. Thanks for that description.


Quote:

Originally Posted by UncleJohn
The -0 option tells xargs to split on a "null" character, which you will have a hard time generating using ls. It's meant to be used in conjunction with the -print0 option of the find command.

While that's true, it doesn't mean a null terminator is required for xargs to function
at all... plus, there is still a discernible difference when used in this example.
Back to the Foo directory:
Code:

$ ls -1t
File One
File Two
$ ls -1t | head -2 | xargs
File One File Two
$ ls -1t | head -2 | xargs -0
File One
File Two

$ ls -1t | head -2 | xargs | od -cb
0000000    F  i  l  e      O  n  e      F  i  l  e      T  w
          106 151 154 145 040 117 156 145 040 106 151 154 145 040 124 167
0000020    o  \n                                                       
          157 012                                                       
0000022
$ ls -1t | head -2 | xargs -0 | od -cb
0000000    F  i  l  e      O  n  e  \n  F  i  l  e      T  w
          106 151 154 145 040 117 156 145 012 106 151 154 145 040 124 167
0000020    o  \n  \n
          157 012 012
0000023

Anyway, I'm glad to have learned something new. Thanks all.

Hal Itosis 03-31-2006 12:26 PM

xargs
 
Sorry to beat this horse again... but when I actually type it out,
I sometimes start to understand it better.

Guess this won't be any big news, but -- while the magical xargs -I%
works wonders on paths with spaces -- it still stumbles on single quotes:
Code:

$ cd Foo; ls -1
File One
File Two
$ touch "Pike's Peak"; ls -1
File One
File Two
Pike's Peak
$ ls -1 | xargs -I% file %
File One: empty
File Two: empty
xargs: unterminated quote

Minor nuisance.
Employing hayne's handy enquoter makes all go well:
Code:

$ ls -1 | sed 's/^.*$/"&"/' | xargs -I% file %
File One: empty
File Two: empty
Pike's Peak: empty

Okay... but what about double quotes then?
Code:

$ ls -1
File One
File Two
Pike's Peak
$ touch "\"Bartlett's Quotations\""; ls -1
"Bartlett's Quotations"
File One
File Two
Pike's Peak
$ ls -1 | xargs -I% file %
Bartlett's Quotations: cannot open (Bartlett's Quotations)
File One: empty
File Two: empty
xargs: unterminated quote
$ ls -1 | sed 's/^.*$/"&"/' | xargs -I% file %
xargs: unterminated quote

Oh oh, enquoter quoted a quote... so that turned
"Bartlett's Quotations" into ""Bartlett's Quotations""
which -in effect- becomes Bartlett's Quotations

Let's tweak enquoter so it won't quote any double quotes:
Code:

$ ls -1 | sed '/"/!s/^.*$/"&"/'
"Bartlett's Quotations"
"File One"
"File Two"
"Pike's Peak"

That much looks right. Now throw xargs back in:
Code:

$ ls -1 | sed '/"/!s/^.*$/"&"/' | xargs -I% file %
Bartlett's Quotations: cannot open (Bartlett's Quotations)
File One: empty
File Two: empty
Pike's Peak: empty

Shoot. How about... "%"
Code:

$ ls -1 | sed '/"/!s/^.*$/"&"/' | xargs -I% file "%"
Bartlett's Quotations: cannot open (Bartlett's Quotations)
File One: empty
File Two: empty
Pike's Peak: empty

Hmmmm... make that \"%\"
Code:

$ ls -1 | sed '/"/!s/^.*$/"&"/' | xargs -I% file \"%\"
"Bartlett's Quotations": empty
"File One": cannot open ("File One")
"File Two": cannot open ("File Two")
"Pike's Peak": cannot open ("Pike's Peak")

Hey... it worked?
(Umm, not really).
FORGET IT.

It's hopeless that way. Must resort to null chars
to manage *all* possible cominations of quotes...
Code:

$ find . -name "*i*" -print0 | xargs -0 -I% file %
./"Bartlett's Quotations" ./File One ./File Two ./Pike's Peak: cannot open (./"Bartlett's Quotations" ./File One ./File Two ./Pike's Peak)

Whoops... xargs is feeding file all 4 found items at once.
Add the -n1 option to pass them one at a time.
Code:

$ find . -name "*i*" -print0 | xargs -0 -n1 -I% file %
./"Bartlett's Quotations": empty
./File One: empty
./File Two: empty
./Pike's Peak: empty

Finally. (whew)

--

But: must we always use find's print0 to talk to xargs -0 ?
The original ls -1t | head -2 had a particular purpose.
Isn't there some way we can insert nulls after any command's list output?

Let's try tr
Code:

$ ls -1 | tr "\n" "\000\n" | xargs -0 -n1 file
"Bartlett's Quotations": empty
File One: empty
File Two: empty
Pike's Peak: empty

HOT DAMN!!!!!!!
Going for broke...
Code:

$ ls -1t | head -2 | tr "\n" "\000\n" | xargs -0 -n1 -I% cp -v % %.bak
"Bartlett's Quotations" -> "Bartlett's Quotations".bak
Pike's Peak -> Pike's Peak.bak
$ ls -1
"Bartlett's Quotations"
"Bartlett's Quotations".bak
File One
File Two
Pike's Peak
Pike's Peak.bak

Now I'm really happy! :D

-HI-

hayne 03-31-2006 02:00 PM

Using 'tr' to change newlines into null characters is a good idea.
But do you still need the newlines if you do that?
I.e. wouldn't
tr "\n" "\000"
work just as well?

Hal Itosis 04-01-2006 01:58 AM

Thanks hayne... guess I got so "caught-up-in-the-moment" that
I wasn't thinking about further code reduction. I wonder though
if that newline might be missed... further down the pipeline. (?)

[No, I guess you're right.]

Well, we're even then:
You trimmed nuller() { /usr/bin/tr "\n" "\000"; } ...and
I tweaked enquoter() { /usr/bin/sed '/"/!s/^.*$/"&"/'; }

;)

(Not of much use I guess, unless the entire "name" was quoted.)


All times are GMT -5. The time now is 05:28 PM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, vBulletin Solutions, Inc.
Site design © IDG Consumer & SMB; individuals retain copyright of their postings
but consent to the possible use of their material in other areas of IDG Consumer & SMB.