0

I'm on bash (Mac OS X). I have a list of files and there's a string I want to remove:

$ grep -l \</html\> *.html  
21888601.html  
21906283.html  
21977081.html  
...

All matching files are named in this format (.html). Then I try this:

$ grep -l \</html\> 27776977.html | xargs -0 sed -i.back '/<\/html>/d'

The shell just prints out the list of files returned from grep and an error:

sed: 21888601.html  
21906283.html  
21977081.html  
...
: File name too long

These filenames are obviously not too long, so there is some other error here. Also, when I test this on files that have alpha names (not all numbers), I don't get the error.

I also tried:

$ grep -l \</html\> 27776977.html | xargs -0 sed -i.back '/<\/html>/d'
sed: 27776977.html
: No such file or directory

$ grep -l \</html\> 27776977.html
27776977.html

Is sed unable to handle numerical filenames? Or is there some other problem here?

2

Because you use the -0 option, xargs will look for a null character, instead of whitespaces to terminate input file name. This causes all files found by grep to concat to a long string instead of separate files.

More details from man xargs:

-0, --null
              Input items are terminated by a null character instead of by whitespace,  and  the  quotes  and
              backslash  are  not  special  (every  character  is taken literally).  Disables the end of file
              string, which is treated like any other argument.  Useful when input items might contain  white
              space,  quote  marks,  or backslashes.  The GNU find -print0 option produces input suitable for
              this mode.

In this case, your file's name don't have any special characters, so you should remove the -0 option.

1

You need -Z option in grep if you use -0 with xargs.

You can see that the error file name to long, lists all the file names concatenated together.

man grep:

-Z, --null
          Output  a  zero  byte (the ASCII NUL character) instead of the character that normally follows a file name.
          For example, grep -lZ outputs a zero byte after each file name instead of the usual newline.   This  option
          makes  the  output  unambiguous,  even  in  the  presence  of file names containing unusual characters like
          newlines.  This option can be used with commands like find -print0, perl -0,  sort  -z,  and  xargs  -0  to
          process arbitrary file names, even those that contain newline characters.

Usually grep, xargs and other commands use a newline or space as a delimiter. But they can be asked to use a null, this is useful when the data has spaces.

xargs uses option -0 to tell it that its input is null delimited, grep uses -Z or --null to tell it to create null delimited output.

If your grep does not support -Z, then remove the -0 from xargs. This should work if the filenames don't have newline characters in them.

  • 1
    This will not work. -Z is a GNU extension that not implement in OS X. You should use --null. – cuonglm Jul 9 '14 at 18:48
  • 1
    @Gnouc In that case make sure files have no space in them, and then remove the -0 from xargs. Or install Gnu tools. – ctrl-alt-delor Jul 9 '14 at 18:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.