What does this Linux shell script line do?

1

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.

JJ01

Posted 2011-07-29T17:53:16.983

Reputation: 223

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 – 2011-07-29T18:32:15.923

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 – 2011-07-29T18:41:02.997

| sort | uniq can be replaced by | sort -u – mouviciel – 2011-07-29T18:45:12.447

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 – 2011-07-29T19:06:47.793

Answers

3

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.

user1686

Posted 2011-07-29T17:53:16.983

Reputation: 283 655

Makes sense now if you assume the grep command is incorrect. – Nicholi – 2011-07-29T18:33:30.073

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 – 2011-07-29T19:08:52.270

BTW what does the -pi do? "man perl" wasn't very helpful. – JJ01 – 2011-07-29T19:11:03.127

@JJ01: Yes, xargs will run perl ... once even if it has no input. // man perlrun, look for -p and -i separately. – user1686 – 2011-07-29T20:32:05.053