The mistake in find and sed command in linux? - linux

I want add some script to my site.
But problem in one thing: site include hundreds of html files.
So I need to create some command to insert code after body tag. How I can do this?
find . -name '*.html' exec sed -i 's/<\/body>/<script src="1.js"><\/script><\/body>/g' {} \;
But it can't work.
Please, fix this command

There is an error in command - replace exec with -exec and should be fine.
find . -name '*.html' exec sed -i 's/<\/body>/<script src="1.js"><\/script><\/body>/g' {} \;

That also works for me:
find * -name "*.html" | xargs -L1 -I{} sed -i 's/<\/body>/<script src="1.js"><\/script><\/body>/g' {}
Changes:
replaced path . with '*'
the'xargs' tool gets all lines from stdin, and executes command separately for each of line, with possibility to pass that line as argument in command, so
in that case this is the same approach as find -cmd, but generally it opens another possibilites (check out the xargs manual).

Related

How can i update the contents of a file by replacing strings using grep and find command

I am finding XML files under particular sub directory having "responsible" word in it. Searching is working fine as shown below.
find . -name '*.xml' -exec grep -H 'responsible' {} \;
./dir1/d1.xml<responsible><></responsible>
./dir2/d2.xml<responsible><SYSTEM></responsible>
./dir3/d3.xml<responsible><SYSTEM></responsible>
... and so on.
Is there a way i can replace all occurrences of SYSTEM with blank one.
result i am looking is:
./dir1/d1.xml<responsible><></responsible>
./dir2/d2.xml<responsible><></responsible>
./dir3/d3.xml<responsible><></responsible>
I would use perl pie
perl -p -i -e 's/<responsible><SYSTEM><\/responsible>/<responsible><><\/responsible>/' `find ./ -name *.xml`

Bash find- is showing the files but returning no such file or directory

I have a bash script I cannot get working. I am a dead set beginner in bash this is actually the first script I've ever used. I'm trying to get omxplayer to play a list of files in a directory. When the script runs I get feedback showing the file then the error that there is no such file or directory. Please help me?
#!/bin/sh
find /media/pi/88DC-E668/MP3/ -name "*.mp3" -exec PLAY={} \;; omxplayer "$PLAY";
This is the echo:
find: `PLAY=/media/pi/88DC-E668/MP3/Dance.mp3': No such file or directory
find: `PLAY=/media/pi/88DC-E668/MP3/Whitemary.mp3': No such file or directory
find: `PLAY=/media/pi/88DC-E668/MP3/Limo.mp3': No such file or directory
find: `PLAY=/media/pi/88DC-E668/MP3/Silo.mp3': No such file or directory
File "" not found.
Easy way:
find /media/pi/88DC-E668/MP3 -name \*.mp3 -exec omxplayer {} \;
or
while IFS= read -r -d '' mp3
do
omxplayer "$mp3"
done < <(find /media/pi/88DC-E668/MP3 -name \*.mp3 -print0)
or
find /media/pi/88DC-E668/MP3 -name \*.mp3 -print0 | xargs -0 -n1 omxplayer
You can omit the -n1 if the omxplayer could handle multiple filenames. In such case the 1st could be written as:
find /media/pi/88DC-E668/MP3 -name \*.mp3 -exec omxplayer {} +
but the simplest probably will be
#shopt -s globstar #the default is on
for mp3 in /media/pi/88DC-E668/MP3/{,**/}*.mp3
do
omxplayer "$mp3"
done
EDIT I stand corrected, but won't delete the answer as you can also learn from the mistakes of others. See comment and rather use this answer :)
So please don't do it like this, as this is a typical "happy path" solution - meaning: it works if you know what you're doing and you know your paths (e.g. that they don't contain spaces). I keep forgetting that many people don't know yet that spaces in paths are evil.
Just use xargs to pass what you found to your player like this:
#!/bin/sh
find /media/pi/88DC-E668/MP3/ -name "*.mp3" | xargs omxplayer
The -exec foo part means run the command foo for each path found.
In your case, -exec PATH={}, the {} part is replaced with the path name, ending up with something like -exec PATH=/media/pi/88DC-E668/MP3/Dance.mp3, and so then find tries to run the command PATH=/media/pi/88DC-E668/MP3/Dance.mp3 which fails because there isn't actually any such program to execute.
xargs is the usual way to do what you're trying to do, as described in another comment already.
You could also do:
find /media/pi/88DC-E668/MP3/ -name \*.mp3 |
while read f; do
omxplayer "$f"
done

How to chop off part of a file extension using find -exec

I want to use "find" to rename a bunch of files, with the rename simply being the removal of part of the extension.
EXAMPLE:
abc.ext.DELAYED --> abc.ext
I've tried the following, but they simply aren't working:
find . -name *.DELAYED -execdir mv {} $(echo {} | sed 's:\.DELAYED::') \;
find . -name *.DELAYED -execdir mv {} $(echo {} | cut -f 1 -d".") \;
There are two problems with your commands.
The first problem is the * in the command. You need to enclose it in a string since otherwise bash would expand it as a glob expression - * expands to all files in the current folder.
The command should look like this:
find . -name '*.DELAYED' ...
The second problem is that command substitutions happen before the command gets executed meaning
$(echo {})
would expaneded to the literal {} will would lead to a command like
mv file1 file1
You can execute the command in a shell instead:
... -execdir bash -c 'mv {} $(echo {} | cut -f2 -d.)' \;
You have specifically tagged this question with "linux", so I assume that your distribution has the rename tool installed, which is bundled in util-linux package.
This avoids command substitution issues and chaining multiple programs:
find . -name '*.DELAYED' -execdir rename .DELAYED '' {} \;

Insert line into multi specified files

I want to insert a line into the start of multiple specified type files, which the files are located in current directory or the sub dir.
I know that using
find . -name "*.csv"
can help me to list the files I want to use for inserting.
and using
sed -i '1icolumn1,column2,column3' test.csv
can use to insert one line at the start of file,
but now I do NOT know how to pipe the filenames from "find" command to "sed" command.
Could anybody give me any suggestion?
Or is there any better solution to do this?
BTW, is it work to do this in one line command?
Try using xargs to pass output of find and command line arguments to next command, here sed
find . -type f -name '*.csv' -print0 | xargs -0 sed -i '1icolumn1,column2,column3'
Another option would be to use -exec option of find.
find . -type f -name '*.csv' -exec sed -i '1icolumn1,column2,column3' {} \;
Note : It has been observed that xargs is more efficient way and can handle multiple processes using -P option.
This way :
find . -type f -name "*.csv" -exec sed -i '1icolumn1,column2,column3' {} +
-exec do all the magic here. The relevant part of man find :
-exec command ;
Execute command; true if 0 status is returned. All following arguments
to find are taken to be arguments to the command until an argument consisting
of `;' is encountered. The string `{}' is replaced by the current file name
being processed everywhere it occurs in the arguments to the command, not just
in arguments where it is alone, as in some versions of find. Both of
these constructions might need to be escaped (with a `\') or quoted to protect
them from expansion by the shell. See the EXAMPLES section for examples of
the use of the -exec option. The specified command is run once for each
matched file. The command is executed in the starting directory. There
are unavoidable security problems surrounding use of the -exec action;
you should use the -execdir option instead

Run expand on find results

I'm trying to run the expand shell command on all files found by a find command. I've tried -exec and xargs but both failed. Can anyone explain me why? I'm on a mac for the record.
find . -name "*.php" -exec expand -t 4 {} > {} \;
This just creates a file {} with all the output instead of overwriting each individual found file itself.
find . -name "*.php" -print0 | xargs -0 -I expand -t 4 {} > {}
And this just outputs
4 {}
xargs: 4: No such file or directory
Your command does not work for two reasons.
The output redirection is done by the shell and not by find. That means that the shell will redirect finds output into the file {}.
The redirection would occur immediately. That means that the file will be written even before it is read by the expand command. So it's not possible to redirect a command's output into the input file.
Unfortunately expand doesn't allow to write it's output into a file. So you have to use output redirection. If you use bash you could define a function that executes expand, redirects the output into a temporary file and move the temporary file back over the original file. The problem is that find will run a new shell to execute the expand command.
But there is a solution:
expand_func () {
expand -t 4 "$1" > "$1.tmp"
mv "$1.tmp" "$1"
}
export -f expand_func
find . -name \*.php -exec bash -c 'expand_func {}' \;
You are exporting the function expand_func to sub shells using export -f. And you don't execute expand itself using find -exec but you execute a new bash that executes the exported expand_func.
'expand' isn't really worth the trouble.
You can just use sed instead:
find . -name "*.php" | xargs sed -i -e 's/\t/ /g'

Resources