0

I have dozens of bash scripts in a certain location (/subdirectory1) with the incorrect pathname (pathname1) within the file. I would like to somehow replace this pathname with pathname2 for all of the bash scripts *.sh within that subdirectory.

Is there a standard way to do this?

In perl, if I was working with a single file file1, I would execute:

perl -pi -e 's/pathname1/pathname2/g' file1

How would one accomplish this for all files, *.sh?

It doesn't have to be in perl, but this is the one way that comes to mind. I suspect there's also a way to do this with other shell scripts and other languages---I will happily edit this question to narrow down the options.

Guildencrantz
  • 1,875
  • 1
  • 16
  • 30
ShanZhengYang
  • 16,511
  • 49
  • 132
  • 234

3 Answers3

2

You can first run find to list the files, then run perl or sed or whatever on them:

find . -name '*.sh' -exec <perl_command> {} \;

Note the {} \;, which means run this for each of the find outputs.

yelsayed
  • 5,236
  • 3
  • 27
  • 38
  • You should specify what you mean by `` (I assume `-name "*.sh"`, but I think `` is pretty self explanatory). – Elliott Frisch Dec 31 '16 at 03:37
  • I think it's kind of orthogonal to the question, but sure. Fixed. – yelsayed Dec 31 '16 at 03:40
  • I was thinking another note at the end like, `` might be `-name "*.sh"` or `-type 'f'` or some kind of combination to indicate the general usage thereof. But putting it inline works too. – Elliott Frisch Dec 31 '16 at 03:42
2

Just list all filenames, and they are all processed line by line

perl -pi -e 's{pathname1}{pathname2}g' *.sh

where {} are used for delimiters so / in path need not be escaped.

This assumes that the *.sh specifies the files you need.


We can see that this is the case by running

perl -MO=Deparse -ne '' file1 file2

which outputs

LINE: while (defined($_ = <ARGV>)) {
    '???';
}
-e syntax OK

This is the code equivalent to the one-liner, shown by the courtesy of -MO=Deparse. It shows us that the loop is set up over input, which is provided by <ARGV>.

So what is <ARGV> here? From I/O Operators in perlop

The null filehandle <> is special: ... Input from <> comes either from standard input, or from each file listed on the command line.

where

<> is just a synonym for <ARGV>

So the input is going to be all lines from all submitted files.

zdim
  • 64,580
  • 5
  • 52
  • 81
1

Just use a file glob:

perl -pi -e 's@pathname1@pathname2@g' *.sh

This will deal with pathological filenames that contain whitespace just fine.

William Pursell
  • 204,365
  • 48
  • 270
  • 300