[svlug] xargs and filenames with shell special characters?

Erik Steffl steffl at bigfoot.com
Thu Oct 4 15:39:01 PDT 2001


"Karsten M. Self" wrote:
> 
> on Thu, Oct 04, 2001 at 04:33:29AM -0700, Erik Steffl (steffl at bigfoot.com) wrote:
> > "Karsten M. Self" wrote:
> > >
> > > on Sun, Sep 23, 2001 at 01:55:25PM -0700, Erik Steffl (steffl at bigfoot.com) wrote:
> > > >   is there any way to make xargs (and other programs) work with files
> > > > that have shell special characters in the filename?
> > > >
> > > >   e.g. there's a file single'quote, how to make following command work:
> > > >
> > > >   find ~ -name single\* -print |xargs ls
> > > >
> > > >   what I get is:
> > > >
> > > > xargs: unmatched single quote
> > > >
> > > >   I know I can put backslash before special character to un-special them
> > > > but that's not possible when list of the filenames is generated by
> > > > program (e.g. find). Is there any solution to this problem? [apart from
> > > > writing (sed/awk/perl etc.) script that would escape all the special
> > > > characters]
> > >
> > > There's the '-print0' and '-0' (that's zero/nil, not letter oh) 'find'
> > > and 'xargs' arguments, which gets you past some issues.
> > >
> > > I tend to migrate to 'for file in $( expression )' processing in this
> > > case, though:
> > >
> > >     for file in $( find ~ -name single\* -print )
> > >     do
> > >         xargs ls "$file"
> > >     done
> > >
> > > ...which seems to work as desired.
> >
> >   thanks, both work (second one without xargs, if anybody's trying it),
> >
> >   one question remains:
> >
> > bash-2.05$ ls rrr*
> > rrr  rrr"rrr  rrr'rrr
> > bash-2.05$ ls rrr*|xargs
> > xargs: unmatched double quote
> >
> >   why does xargs care about single quote? and why it suddenly does not
> > care when one uses -0? I mean -0 is useful with find's -print0 but does
> > not help in other cases (one has to use for loop approach in those cases
> > which xargs was designed to replace).
> >
> >   based on man page the xargs should simply read stdin, line by line,
> > and supply it to the command (or echo, if no command is given). this
> > unmatched quote stuff looks more like a bug then a feature...
> 
> Good question.  My original flip response was going to be:
> 
>     Because xargs *is* reading the input line by line.  And if you pass
>     in stdin to a process line by line, and quote the carriage return,
>     you've got a quoted carriage return.
> But I tried modifying your problem to balance the quotes:
> 
>     $ touch 'aaa"aaa' "bbb'bbb" 'ccc"ccc'
> 
> ...which should render as:
> 
>     aaa"aaa bbb'bbb ccc"ccc
> 
> ...where you've essentially quoted "aaa bbb'bbb ccc".
> 
> ...but it doesn't work without the '-print0/-0' trick.  I'm not sure if
> this is a shell issue or an xargs issue, I suspsect the latter.  Any
> gurus know what's going on?

  well, I found that the xargs treats the blanks as argument separators,
you can use quotes or '\' to escape them. that seems like a very bad way
to do the processing since you have no way to process strings (e.g.
filenames) that contain special characters ([ '"]).

  the -0 is gnu extension (aparently to get around this problem, but
usable only with corresponding gnu find, not other shell tools) so I
guess there is no (portable) way to solve this problem... that just
sucks.

  yes, you can use the loop but that's what the xargs is designed to
replace...

  anybody knows the reasoning for the current operation of xargs?

  TIA

	erik




More information about the svlug mailing list