redirecting output of 'find' command to 'vim' - 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.

Related

How to grep contents from list of files from Linux ls or find command

I am running -> "find . -name '*.txt'" command and getting list of files.
I am getting below mention output:
./bsd/contrib/amd/ldap-id.txt
./bsd/contrib/expat/tests/benchmark/README.txt
./bsd/contrib/expat/tests/README.txt
./bsd/lib/libc/softfloat/README.txt
and so on,
Out of these files how can i run grep command and read contents and filter only those files which have certain keyword? for e.g. "version" in it.
xargs is a great way to accomplish this, and its already been covered.
The -exec option of find is also useful for this. It will perform a command over all files returned from find.
To invoke grep as few times as possible, passing multiple filenames to each call:
find . -name '*.txt' -exec grep -H 'foo' {} +
Alternately, to invoke grep exactly once for each file found:
find . -name '*.txt' -exec grep -H 'foo' {} ';'
In either case, {} is like a placeholder for the values from find; if your shell is zsh, it may be necessary to escape it, as in '{}'.
There are several ways to accomplish this.
If there are non-.txt files which might usefully contain the keyword:
grep -r KEYWORD *
This uses the recursive directory search option of grep.
To search only .txt files:
find . -name '*.txt' -exec grep KEYWORD {} \;
or
find . -name '*.txt' -exec grep KEYWORD {} +
or
find . -execdir grep KEYWORD {}
The first runs grep for each matching file. The second runs grep much fewer times, accumulating many matched files before invoking grep. The third form runsgrep` once in every directory.
There is usually a function built into find for that, but to be portable across platforms, I typically use xargs. Say you want to find all the xml files in or below the current directly and get a list of each occurrence of 'foo', you can do this:
find ./ -type f -name '*.xml' -print0 | xargs -0 -n 1 grep -H foo
It should be self-explanatory except for the -print0, which separates filenames with NULs rather than newlines, and the -0, which tells xargs to use those NULs rather than interpreting spaces and quotes as syntax (which can confuse it if filenames contain either).

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

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

Vim: Find and replace in a large project?

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.

How to use cscope with paths that contain spaces

There are some folder that contains space, and as a result, those folders can not be indexed using cscope.
Can i ask you for help to solve this,or any suggestion.
thanks
Julius
Thanks for your reply.
My steps to use cscope like the following
find . -name '*.scala'>cscope.files
cscope -b
at this step. i see the message indicates that can not find file:
cscope: cannot find file /work/project/copy
cscope: cannot find file of
cscope: cannot find file fp/src/main/jav....
Actually copy of fp is a folder.so i think cscope can not recognize the folder contains space.
I encountered this problem when i tried to use vim with cscope.maybe i need move this question to other tag.
You can do it simply using GNU find at least, you can use the -printf or -fprintf options for that:
find . -type f -fprintf cscope.files '"%p"\n'
pydave's answer is very slow. This way took 0.10s where pydave's answer took 14s:
find . -name "*.scala" | awk '{print "\""$0"\""}' > cscope.files
You can use find's -exec to force quotes around your output:
find . -name "*.scala" -exec echo \"{}\" \; > cscope.files
You might need to mess around with quoting/escaping if you're doing this from a script.
Double quoting the files names works in cygwin, where as escaping with backslash does not.
$ find $PWD -name "*.scala" | sed -e 's/^/"/g' -e 's/$/"/g' > cscope.files

Resources