4

On a Mac; I'm using Hazel to run a shell script, in order to find & replace text in .txt files in multiple subdirectories inside my Downloads folder. My script.sh file lives somewhere else (/Users/admin/Desktop)

script.sh looks like this currently:

#!/bin/bash
cd /Users/admin/Downloads/
perl -pi -w -e 's/OldText/NewText/g;' *.txt

It works, but doesn't look through all the subdirectories inside Downloads. How do I do that?

MANOJ GOPI
  • 1,279
  • 10
  • 31
guisauer
  • 93
  • 2
  • 7

2 Answers2

3

Use find and xargs

Something similar to (NOT TESTED!):

find /Users/admin/Downloads/ -type f -print0 | xargs -0 perl -pi -w -e 's/OldText/NewText/g;' 
1

I'm not sure why you would need perl in this case, and I'm not sure who Hazel is and why she would run your shell script, but since you've flagged your question shell and are obviously using bash, I'll provide a shell-only answer. Note that this will work in other shells too, not just bash.

#!/bin/bash

find /Users/admin/Downloads/ -type f -name "*.txt" \
  -exec sed -i '' -e 's/OldText/NewText/g' {} \;

Note that this find command is split into two lines for easier readability. It uses sed instead of perl because sed is smaller and likely faster, and is considered a standard shell tool whereas perl may not be found on all systems.

Note also that the exact syntax of the sed options I've used may depend on the implementation of sed that is on your system.

The find command works like this:

find [path ...] [command ...]

You can man find to see the details, but the command I've provided here does the following.

  • Starts in /Users/admin/Downloads/
  • -type f - Looks for things that are files (as opposed to directories or symlinks)
  • -name "*.txt" - AND looks for things that match this filespec
  • -exec ... - AND executes the following shell command, replacing {} with the filename that's been found.
ghoti
  • 45,319
  • 8
  • 65
  • 104
  • 4
    Hm. This removed the complete content of all my files (with specified ending) in the directory. – User Dec 09 '16 at 10:51
  • @Ixx - I'd need to see your exact command line to be able to tell you why. Along with your operating system, and/or version of `sed`. Most likely, your sed script (or the RE in it) is incorrect. Please feel free to [ask a question](http://stackoverflow.com/questions/ask). – ghoti Dec 09 '16 at 14:50
  • This removed complete content for my files too. sed -i '' 's/OldText/NewText/g' {} \; (removing -ne) fixed it. – Nick Lothian May 19 '22 at 23:47
  • @NickLothian and @User .. wow, I can't believe that error has been there for 7 years. The issue was just the `-n`, which suppresses output, requiring lines to be printed explicitly. Yes, it's not required in this case. I have removed it. – ghoti May 24 '22 at 10:22
  • @ghoti - excellent, thanks for the update. I found the answer useful! – Nick Lothian May 25 '22 at 08:39