8

I am trying to replace a string ::: with :: for all lines in a batch of txtfiles (it can be considered as a word since there's always a space in front and behind it.

I can do it with python like below, but is there a less 'over-kill' / convoluted way of doing this through the unix terminal? (Many pipes allowed)

indir = "./td/"
outdir =  './od/'
for infile in glob.glob(os.path.join(indir,"*")):
  _,FILENAME = os.path.split()
  for l in codecs.open(infile,'r','utf8').readlines():
    l = l.replace(":::","::").strip()
    outfile = codecs.open(os.path.join(outdir,FILENAME),'a+','utf8')
    print>>outfile, l

Then i move all files from od to td mv ./od/* ./td/*

2 Answers 2

22
find . -name "./td/*.c" -exec sed -i "s/:::/::/g" '{}' \;

No need for od/ at all.

EDIT:

A slightly simpler variation:

ls td/*.c | xargs sed -i '' "s/:::/::/g"
Sign up to request clarification or add additional context in comments.

4 Comments

Simpler and much more efficient as well. You can make the find version just as efficient if you use + instead of \; at the end.
-1 for using ls to handle file names. I would add another one for missing the obvious "simpler" solution sed -i ... td/*.c (with a globstar added if needed). And another one for using directory names in find's -name option (see: linux.about.com/od/commands/l/blcmdl1_find.htm)... How did this get 4 votes ?
@Sorin: I admit I don't account for special characters in source file names (figuring that those who use them deserve what they get), but apart from that I don't see the problem. Kudos for your td/*.c suggestion though, I didn't know that would work; I'd've added it to my answer (with attribution) if it had been suggested with more courtesy.
I don't know if I need to laugh or to cry.` sorin@sorin:~/tmp$ find -name "./tc/*.c" find: warning: Unix filenames usually don't contain slashes (though pathnames do). That means that '-name ./tc/*.c'' will probably evaluate to false all the time on this system. You might find the '-wholename' test more useful, or perhaps '-samefile'. Alternatively, if you are using GNU grep, you could use 'find ... -print0 | grep -FzZ ./tc/*.c''.`
3

A simple loop to process each file with sed should suffice.

for inp in ./td/*; do
    fname=${inp##*/}
    sed 's/:::/::/g' "$inp" > ./od/"$fname"
done

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.