I have a folder which includes several files named order[ID].log where [ID] is a string e.g.


I need to write a script in Linux to grep each file by the ID in their name and output the result to a file named ID.log Example:
For orderID1.log, I need to grep 'ID1' orderID1.log > ID1.log
For orderID2.log, I need to grep 'ID2' orderID2.log > ID2.log
I tried to write the script below,

for i in ORDER*.log 
grep 'i' order$i > $i.log;

The problem here is that i will be record as "orderID1","orderID2" rather than "ID1","ID2". Is there a simple way to do this in linux ?

  • Hi @don_crissti, the key word will be the ID after order. To be simply, I write them as 1,2,3,4,...etc. Then I need to grep these ID in the file and save them in a new file. Unfortunately, I don't have them listed in a file. – Alan Yu Oct 30 '15 at 15:14
  • Cool @don_crissti You are right. They are in the same directory. – Alan Yu Oct 30 '15 at 15:27

You'll have to extract the ID substring from the file names. One way to do that is via parameter expansion e.g. ${var:offset:length} so in your case var is filename, offset is 5 (order) and length is ${#f}-9 (that is, total length ${#f} minus the combined length of order and .log which is 9 characters):

for f in order*.log                                                 
    grep -- "$ID" "$f" > "$ID".log

or if you prefer a one-liner:

for f in order*.log; do ID=${f:5:${#f}-9}; grep -- "$ID" "$f" >" $ID".log; done

Alternatively, you could use awk to apply the same action to multiple files:

awk '
id=substr(FILENAME, 6, length(FILENAME)-9)
$0 ~ id{
print > fname
' order*.log

This does all files with one awk invocation, avoiding the shell loop. In one line:

awk 'FNR==1{if(f)close(f);id=substr(FILENAME, 6, length(FILENAME)-9);f=id".log"} $0~id{print > f}' order*.log

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.