Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to determine exactly what the following line of shell script is doing.:

grep --files-with-matches '>' . | sort | uniq | xargs perl -pi~ -e 's/9Kp/9K /' /home/user/DATAFILE.DAT

I'm pretty sure it's attempting to to a global search on '9Kp' and replace with '9K ' in the specified data file, however I'm not clear on what the grep command is doing before that.

share|improve this question
That is a little strange... well the --files-with-matches simply lists names instead of the matching lines, and obviously the search string is '>'. But the fact that the file being searched is simply the current directory '.' is weird. Not quite sure how that is supposed to work, never ouputs anything here. Is this just plain ole GNU grep? – Nicholi Jul 29 '11 at 18:32
There are a number of things wrong with that script. Are you sure you copied it correctly? For example, the . is telling grep to search the current directory, not the files in the current directory but the directory itself. That won't do anything. – garyjohn Jul 29 '11 at 18:41
| sort | uniq can be replaced by | sort -u – mouviciel Jul 29 '11 at 18:45
Yep, I copied it exactly - the only thing changed is the path and .DAT filename. Thanks, I suspected it was broken but wasn't sure if I was reading it wrong. It was probably meant to be grep --files-with-matches '>' *. – JJ01 Jul 29 '11 at 19:06
up vote 3 down vote accepted
grep --files-with-matches '>' .

Search for > in the current directory (.) and print only the filenames of matching files (--files-with-matches).

Note that grep will not return anything if you give it a directory (.) but forget to enable "recursive" mode. The correct command would be

grep --files-with-matches --recursive '>' .

or simply

grep -Rl '>' .

| sort
| uniq

Sort results, and remove duplicates.

| xargs perl -pi~ -e 's/9Kp/9K /' /home/user/DATAFILE.DAT

Run the given command (perl ...) with every word1 from stdin passed as additional arguments.

Every file from the grep results, and also the /home/user/DATAFILE.DAT file, are updated by replacing the text "9Kp" with "9K ". The old files are backed up with a trailing tilde.

1 Note: word, not line. This means that a filename with spaces will be treated as several names. xargs -d'\n' would be better, although not perfect.

share|improve this answer
Makes sense now if you assume the grep command is incorrect. – Nicholi Jul 29 '11 at 18:33
Just want to be sure I understand you correctly - even though the "grep" command will find nothing, perl will still be invoked (and thus the search/replace performed) on the .DAT file? Thanks – JJ01 Jul 29 '11 at 19:08
BTW what does the -pi do? "man perl" wasn't very helpful. – JJ01 Jul 29 '11 at 19:11
@JJ01: Yes, xargs will run perl ... once even if it has no input. // man perlrun, look for -p and -i separately. – grawity Jul 29 '11 at 20:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .