Vim: Find and replace in a large project? - vim

There's a way to replace all occurencies of a string in files in Vim using a combination of args and argdo commands. Unfortunately there's a drawback with this solution: It will open all files which may be a problem for large projects. Does anyone know more compact and memory efficient way?

find projectfolder -type f -exec grep -Iq 'pattern' {} \; -exec vim {} +

Here's how I do it (when I'm not using perl):
find . -name '*.java' -exec vim +'%s/OldName/NewName/gc' +'wq' {} \;
i.e. replace "OldName" with "NewName" in all "*.java" files, but prompt me for confirmation for each substitution.

Related

How to find and rename all files using -exec

I want to rename all files which end on ".mp4" in such way that instead of white spaces to contain underscores.
Example:
Original file -> test 1.mp4
Renamed file -> test_1.mp4
I was trying with:
find . -iname "*.mp4" -exec mv {} $(echo '{}' | tr " " "_") \;
But I got only:
mv: ‘./test 1.mp4’ and ‘./test 1.mp4’ are the same file
It seems that my pipe is not working.I would appreciate all ideas.
It seems that the only way to do it so far is via "rename" command.
Here is the command that worked:
find /tmp/test/ -iname "*.mp4" -exec rename " " "_" "{}" \;
I'd look into using the rename command, assuming your distribution provides it. In Debian: https://packages.debian.org/rename
If you don't need to search in subdirectories:
rename 's/\ /_/' *.mp4
If you do:
find . -iname "*.mp4" -execdir rename 's/\ /_/' {} \;
If multiple spaces must be replaced, the search/replace expression becomes 's/\ /_/g'
If you really want to keep your syntax/approach, see this very similar question: find -exec with multiple commands

Use find results as command line argument for another process

How can I use find results as a command line argument for another process?
For example:
find -type f -iname "server*error*log" | vim ??
How to make vim to open returned filename?
You need to use the -exec option of find:
find -type f -iname "server*error*log" -exec vim {} \;
The placeholder {} will get replaced by the actual filename. The -exec command needs to get terminated with the \;.
If you want not just one file, but many, to be acted on by one program (in your case editing in Vim), I think you want to pass it to xargs:
find -type f -iname "server*error*log" | xargs vim

How to use find to make copies of file with prefix in CSH?

I am trying to make copies of certain file and let them have a prefix.
in order to do it I thought of using find. for our use, let's call them kuku files and I want them to have a "foo" prefix:
find . -maxdepth 1 -name "kuku*" -exec cp '{}' foo_'{}' \;
but it doesn't work because the find always starts the results with ./ so i get a lot of error messages saying "cp: cannot create regular file `foo_./kuku...`: No such file or directory".
the problem is solvable by using foreach f (`ls`) and than using grep and the status var, but it is cumbersome and I want to learn a better solution (and improve my knowledge of the find command along the way...).
update foreach solution (which I don't like and want your help in finding a replacement):
foreach f (`ls`)
echo $f | grep -lq kuku
if (! $status) then
cp $f foo_$f
endif
end
but this is UGLY! (end of update)
as the header says, I'm using csh - not because I love it, just because that's what we use at work...
update
trying to use basename as a solution, because find -exec basename '{}' \; removes the ./ prefix, but i failed using the basename inside the find with backticks (`), meaning that
find -name "kuku*" -exec cp '{}' foo_`basename '{}` \;
simply doesn't work.
Here you go.. I have tested in my linux box
find . -name "kuku*" -exec sh -c 'cp {} foo_`basename {}`' \;

redirecting output of 'find' command to 'vim'

I am doing a find $PWD -name 'filename' | vim -
expecting the file filename to be opened in vim editor. but it is not working.
In this case, I am sure that there exists just one file with name 'filename'.
Also the result of find gives the complete path on stdout.
vim "$(find "$PWD" -name 'filename')"
or
find "$PWD" -name 'filename' -exec vim {} \;
(You can drop "$PWD", by the way. find starts the search from current directory by default.)
find . -name 'filename' -print0 | xargs -0 vim
should also work. You might want to read up on xargs, which is a handy thing to know about.
Mentioned in #idbrii's comment, but my favorite is:
find . -name 'filename' -type f -exec vim {} \+
This opens up each file found in its own buffer ready to be navigated with :next and :prev. Tested on OSX, but I'm fairly certain it will work on Linux too.
One way I find is very easy is enclosing the find command with backticks (character under tilde on most keyboards) and passing it to vim.
vim `find . -name myfile`
In fact, you can use backtick for any command to get the literal string output of the command.

Can the find command's "exec" feature start a program in the background?

I would like to do something like:
find . -iname "*Advanced*Linux*Program*" -exec kpdf {} & \;
Possible? Some other comparable method available?
Firstly, it won't work as you've typed, because the shell will interpret it as
find . -iname "*Advanced*Linux*Program*" -exec kpdf {} &
\;
which is an invalid find run in the background, followed by a command that doesn't exist.
Even escaping it doesn't work, since find -exec actually execs the argument list given, instead of giving it to a shell (which is what actually handles & for backgrounding).
Once you know that that's the problem, all you have to do is start a shell to give these commands to:
find . -iname "*Advanced*Linux*Program*" -exec sh -c '"$0" "$#" &' kpdf {} \;
On the other hand, given what you're trying to do, I would suggest one of
find ... -exec kfmclient exec {} \; # KDE
find ... -exec gnome-open {} \; # Gnome
find ... -exec xdg-open {} \; # any modern desktop
which will open the file in the default program as associated by your desktop environment.
If your goal is just not having to close one pdf in order to see the next one as opposed to display each pdf in its own separate instance, you might try
find . -iname "*Advanced*Linux*Program*" -exec kpdf {} \+ &
With the plussed variant, -exec builds the command line like xargs would so all the files found would be handed to the same instance of kpdf. The & in the end then affects the whole find. With very large numbers of files found it might still open them in batches because command lines grow too long, but with respect to ressource consumption on your system this may even be a good thing. ;)
kpdf has to be able to take a list of files on the command line for this to work, as I don't use it myself I don't know this.

Resources