Insert the same text file inside several text files - sed

I would like to insert the content of a text file, let's call it Menu.incl inside several different files. I know how to do that on a single file, by using the sed command and by introducing a mark in the target file:
sed -e '/the Menu is Here/r Menu.incl' F.html > F_Menu.html
I want to keep the original file for possible future evolution of the Menu.incl file.
How could I do that for each member of a collection of html files ? My guess : with the find command? I tried to obtain the expected result with the following command:
find . -name '*.html' -exec sed -e '/the Menu is Here/r Menu.incl' '{}' +
but I don't know how to save each modified .html content inside a copy, i.e. without spoiling the original html files
Than you for your help,
Romuald

Try with process substitution:
while read f; do
d=$(dirname "$f")
b=$(basename "$f")
b="new.$b"
sed -e '/the Menu is Here/ r Menu.incl' "$f" > "$d/$b";
done < <(find . -type f -iname "*.html" -print)

Related

Sed * only modifying first file

I would like to delete the first 40 lines of a good number of ASCII files and save the ASCII files without those 40 lines
I'm working under OSX High Sierra, realized that the -i option in sed was not working unless I create a backup file, so I tried using this command:
sed -i'backup' -e '1,40d' *.txt
It however only modifies and deletes the first 40 lines in my first file (alphabetically), but not the others.
How can I edit multiple files with just one command?
Thanks
You can use the following command that will
look in the current folder
ignore sub folder
take only into account files whose filenames end with '*.txt'
before executing the sed command.
Command:
find . -maxdepth 1 -type f -name '*.txt' -exec sed -i 'backup' -e '1,40d' {} \;

sed is appending code in the wrong place in all but one file in a directory

I have the following tab indented code in a bunch of files in a directory:
'oracleServers': dcoDatabaseServers,
'oracleHomes': dcoDatabaseHomes,
'sysPasswords': dcoSYSPasswords,
I want to add 'useOracleDriver': useOracleDriver, after the 'oracleHomes' line in all files. I have this command:
sed -i "/oracleHomes/ a \\\t\t\t\t\t\t\t\t'useOracleDriver': useOracleDriver," $(find . -type f -name 'tc*')
When I run the command, the first file in alpha order with a tc* name, the text gets appended properly:
'oracleServers': dcoDatabaseServers,
'oracleHomes': dcoDatabaseHomes,
'useOracleDriver': useOracleDriver,
'sysPasswords': dcoSYSPasswords,
but with all other files beginning with tc*, I see the 'useOracleDriver': useOracleDriver line, but it's appended to the very end of the file. Any idea on how to get the command to append in the proper place in all the other files?
Try running the sed command on each file individually, instead of all on a single sed execution:
find . -type f -name 'tc*' -exec sed -i "/oracleHomes/ a \\\t\t\t\t\t\t\t\t'useOracleDriver': useOracleDriver," {} \;
or
for f in $(find . -type f -name 'tc*'); do sed -i "/oracleHomes/ a \\\t\t\t\t\t\t\t\t'useOracleDriver': useOracleDriver," $f; done
The advantage of the second format is that, in the event you're not using GNU sed (and therefore have no -i), you can change it to
for f in $(find . -type f -name 'tc*'); do sed "/oracleHomes/ a \\\t\t\t\t\t\t\t\t'useOracleDriver': useOracleDriver," $f > $f.tmp; mv $f.tmp $f; done

unix find and replace text in dir and subdirs

I'm trying to change the name of "my-silly-home-page-name.html" to "index.html" in all documents within a given master directory and subdirs.
I saw this: Shell script - search and replace text in multiple files using a list of strings.
And this: How to change all occurrences of a word in all files in a directory
I have tried this:
grep -r "my-silly-home-page-name.html" .
This finds the lines on which the text exists, but now I would like to substitute 'my-silly-home-page-name' for 'index'.
How would I do this with sed or perl?
Or do I even need sed/perl?
Something like:
grep -r "my-silly-home-page-name.html" . | sed 's/$1/'index'/g'
?
Also; I am trying this with perl, and I try the following:
perl -i -p -e 's/my-silly-home-page-name\.html/index\.html/g' *
This works, but I get an error when perl encounters directories, saying "Can't do inplace edit: SOMEDIR-NAME is not a regular file, <> line N"
Thanks,
jml
find . -type f -exec \
perl -i -pe's/my-silly-home-page-name(?=\.html)/index/g' {} +
Or if your find doesn't support -exec +,
find . -type f -print0 | xargs -0 \
perl -i -pe's/my-silly-home-page-name(?=\.html)/index/g'
Both pass to Perl as arguments as many names at a time as possible. Both work with any file name, including those that contains newlines.
If you are on Windows and you are using a Windows build of Perl (as opposed to a cygwin build), -i won't work unless you also do a backup of the original. Change -i to -i.bak. You can then go and delete the backups using
find . -type f -name '*.bak' -delete
This should do the job:
find . -type f -print0 | xargs -0 sed -e 's/my-silly-home-page-name\.html/index\.html/g' -i
Basically it gathers recursively all the files from the given directory (. in the example) with find and runs sed with the same substitution command as in the perl command in the question through xargs.
Regarding the question about sed vs. perl, I'd say that you should use the one you're more comfortable with since I don't expect huge differences (the substitution command is the same one after all).
There are probably better ways to do this but you can use:
find . -name oldname.html |perl -e 'map { s/[\r\n]//g; $old = $_; s/oldname.txt$/newname.html/; rename $old,$_ } <>';
Fyi, grep searches for a pattern; find searches for files.

SED Delete lines and replace with new from file

Have been looking at SED documention but need a little pointer in the right direction
I have 200 files I want to modify in a batch.
Source is html file.
Need to create a new file for the changes.
Want to delete the first part of each file up to the first tag (This is 20 or so lines but can vary slightly).
Then insert the contents of a source file (the same for all files) into the new target file starting at line 1, for 30 or so lines. The number of lines to insert does not match the number that are deleted though.
Hope you can help.
Paul
This can certainly be done with sed(1), but I would probably use the vanilla editor ed(1).
$ cat > bigfix.sh
for i in "$#"; do
ed "$i" << \eof
1,/<tag>/-1d
0r otherfile.html
w
q
eof
done
$ sh bigfix.sh file*.html
This shell script takes arguments and runs ed(1) on each arg. It deletes lines starting from the first and ending on the line right before the one with <tag>. It then puts otherfile.html at the top and writes out the result.
For an individual file:
sed -e '1,/tag/{/tag/r insertfile' -e ';d}' inputfile > outputfile
For many files:
find . -name 'criterion*.ext' -type f -exec sh -c 'sed -e "1,/tag/{/tag/r insertfile" -e ';d}" "{}" > "{}.new"' \;
Edit:
Fixed the find command to use sh because of the redirection. Note the change in quoting from the previous version.

sed command to write the name of file to HTML comment

I'm looking for a sed command that, with find, I can take a directory tree of JSP files and write the name of the file in an HTML comment to the top of the file.
This will allow me to review a legacy application JSP call tree of in the HTML source.
I'm thinking it will be a one liner for a talented sed guru...
something like:
find . -name '.jsp' -exec sed ? ? ? {} \;
Maybe something using xargs is more appropriate, but I think sed is the tool that will do the work.
If you want to use sed, you can try
find -name "*.jsp" -exec sed -i '1i <!-- {} -->' {} \;
Works fine for me in the presence of /.
On Unix the filename will contain slashes (/) which are special characters for sed, so I would recommend this simpler approach that writes the filename at the bottom of the file:
find . -name '*.jsp' -exec sh -c "echo '<\!-- {} -->' >> '{}'" \;
To write the filename at the top of the file use this:
find . -name '*.jsp' -exec sh -c \
'echo "<!-- {} -->" > "{}.new" && cat "{}" >> "{}.new" && mv "{}.new" "{}"' \;
N.B. The filename might contain characters that might render your HTML invalid, e.g. &, although I doubt that a JSP could have such a strange name.