Shell script traversing the all subdirectories and modifying the content of files - shell

I need to modify a number of files inside a directory. I need to modify all those files which contain particular text and have to replace with some new text.
So I thought of writing a shell script which will traverse through all the subdirectories and modify the content but I'm having problem while traversing the all possible directories.

You can use find to traverse through subdirectories looking for files and then pass them on to sed to search and replace for text.
e.g.
find /some/directory -type f -name "*.txt" -print -exec sed -i 's/foo/bar/g' {} \;
will find all txt files and replace foo with bar in them.
The -i makes sed change the files in-place. You can also supply a backup-suffix to sed if you want the files backed up before being changed.

GNU find
find /some_path -type f -name "*.txt" -exec sed -i 's/foo/bar/g' "{}" +;

http://git.savannah.gnu.org/cgit/bash.git/tree/examples/functions/recurse
:)

You want find.

for n in $(find | grep txt$)
do
echo $n
modify_content.sh $n
done

Related

Get all occurrences of a string within a directory(including subdirectories) in .gz file using bash?

I want to find all the occurrences of "getId" inside a directory which has subdirectories as follows:
*/*/*/*/*/*/myfile.gz
i tried thisfind -name *myfile.gz -print0 | xargs -0 zgrep -i "getId" but it didn't work. Can anyone tell me the best and simplest approach to get this?
find ./ -name '*gz' -exec zgrep -aiH 'getSorById' {} \;
find allows you to execute a command on the file using "-exe" and it replaces "{}" with the file name, you terminate the command with "\;"
I added "-H" to zgrep so it also prints out the file path when it has a match, as its helpful. "-a" treats binary files as text (since you might get tar-ed gzipped files)
Lastly, its best to quote your strings in case bash starts globbing them.
https://linux.die.net/man/1/grep
https://linux.die.net/man/1/find
Use the following find approach:
find . -name *myfile.gz -exec zgrep -ai 'getSORByID' {} \;
This will print all possible lines containing getSORByID substring

How to delete a file except in any one of the subdirectory using shell script

Hi I want to delete a file from any of the subdirectories except one of the subdirectory.
For ex
folder a->a.txt
folder b->subdir 1 -> msgdir-> a.txt
folder c->
Now i want to delete a.txt only in folder a but not the file in msgdir .msgdir can be in any level of subdirectories as it would be changing.
Please help me to resolve this.
This will ignore specifically the msgdir at any level and remove a.txt except in msgdir.
find . ! -path '*/msgdir/*' -name a.txt -type f -delete
Tested with GNU find 4.4.2 and BSD find (Mac Yosemite).
The following approach is overkill if you have GNU find (or a newer BSD one), with the -path option. Otherwise, read on...
You haven't specified which shell you're using but if you have bash, you could go with something like this:
find -name a.txt -exec bash -c "[[ '{}' != */msgdir/* ]]" \; -print
This filters out paths containing /msgdir/, as the test will only pass if the file path doesn't contain the string. If you're happy with the results, you can change -print to -delete.
Without bash, you could use grep to determine the match:
find -name a.txt -exec sh -c "printf '%s' '{}' | grep -qv '/msgdir/'" \; -print

Recursively strip pattern from filename?

Is there a way for me to use the find command to recursively loop through a directory and strip a pattern from the filename?
For example, if I have:
styles.css?c=123456
as a saved file, I would like to be able to loop through the files and match anything that has the wildcard *.css?* and then turn that styles.css?c=123456 into styles.css.
Try this:
find -type f -name '*.css*' -exec echo 'FILE="{}"; mv ${FILE} ${FILE%\?*} ' \; | bash

Bash: recursively copy and rename files

I have a lot of files whose names end with '_100.jpg'. They spread in nested folder / sub-folders. Now I want a trick to recursively copy and rename all of them to have a suffix of '_crop.jpg'. Unfortunately I'm not familiar with bash scripting so don't know the exact way to do this thing. I googled and tried the 'find' command with the '-exec' para but with no luck.
Plz help me. Thanks.
find bar -iname "*_100.jpg" -printf 'mv %p %p\n' \
| sed 's/_100\.jpg$/_crop\.jpg/' \
| while read l; do eval $l; done
if you have bash 4
shopt -s globstar
for file in **/*_100.jpg; do
echo mv "$file" "${file/_100.jpg/_crop.jpg}"
one
or using find
find . -type f -iname "*_100.jpg" | while read -r FILE
do
echo mv "${FILE}" "${FILE/_100.jpg/_crop.jpg}"
done
This uses a Perl script that you may have already on your system. It's sometimes called prename instead of rename:
find /dir/to/start -type f -iname "*_100.jpg" -exec rename 's/_100/_crop' {} \;
You can make the regexes more robust if you need to protect filenames that have "_100" repeated or in parts of the name you don't want changed.

Bash: any command to replace strings in text files?

I have a hierarchy of directories containing many text files. I would like to search for a particular text string every time it comes up in one of the files, and replace it with another string. For example, I may want to replace every occurrence of the string "Coke" with "Pepsi". Does anyone know how to do this? I am wondering if there is some sort of Bash command that can do this without having to load all these files in an editor, or come up with a more complex script to do it.
I found this page explaining a trick using sed, but it doesn't seem to work in files in subdirectories.
Use sed in combination with find. For instance:
find . -name "*.txt" | xargs sed -i s/Coke/Pepsi/g
or
find . -name "*.txt" -exec sed -i s/Coke/Pepsi/g {} \;
(See the man page on find for more information)
IMO, the tool with the easiest usage for this task is rpl:
rpl -R Coke Pepsi .
(-R is for recursive replacement in all subdirectories)
Combine sed with find like this:
find . -name "file.*" -exec sed -i 's/Coke/Pepsi/g' {} \;
find . -type f -exec sed -i 's/old-word/new-word/g' {} \;
I usually do it in perl. However watch out - it uses regexps which are much more powerful then normal string substitution:
% perl -pi -e 's/Coke/Pepsi/g;' $filename
EDIT I forgot about subdirectories
% find ./ -exec perl -pi -e 's/Coke/Pepsi/g;' {} \;
you want a combination of find and sed
You may also:
Search & replace with find & ed
http://codesnippets.joyent.com/posts/show/2299
(which also features a test mode via -t flag)

Resources