Display multiple files in Linux/Unix - linux

I'm looking to display 3 different files, if they exist. I thought the following would work, but it doesn't:
ls -R | grep 6-atom2D.vector$ 6-atom2D.klist 6-atom2D.struct
How can I do it?

Knowing the (base) filenames, you can use find:
find . -name '6-atom2D.vector$' -o -name '6-atom2D.klist' -o -name '6-atom2D.struct'
It searches recursive by default.
For case-insensitive search, use -iname instead.

ls -R | egrep "6-atom2D\.vector$|6-atom2D\.klist|6-atom2D\.struct"
If $ is supposed to be end of line regexp, then you might need to use \> instead. That works for me at least.
Edit: Backslash before .

Related

Select files from a list of files

I have a list of filenames which look like this:
tRapTrain.Isgf3g.2853.2.v1.primary.RC.txt tRapTrain.Yox1.txt
tRapTrain.Isgf3g.2853.2.v1.primary.txt tRapTrain.Ypr015c.txt
tRapTrain.Isgf3g.2853.2.v1.secondary.RC.txt tRapTrain.Yrm1.txt
tRapTrain.Isgf3g.2853.2.v1.secondary.txt tRapTrain.Zbtb12.2932.2.v1.primary.RC.txt
Now i need to select the files with primary.txt and all the files where no final suffix is found. final suffix == primary.RC.txt , secondary.RC.txt, secondary.txt.
So my desired output will be:
tRapTrain.Isgf3g.2853.2.v1.primary.txt
tRapTrain.Yox1.txt
tRapTrain.Ypr015c.txt
tRapTrain.Yrm1.txt
I tried to do it with ls tRap*primary.txt but cant figure out how to do both selections at once. Any help is appreciated.
You can use find:
find * -type f -not -name "*.secondary.RC.txt" -not -name "*.primary.RC.txt" -not -name "*.secondary.txt" -print
Using Shopt:
$ shopt -s extglob
$ ls !(*primary.RC.txt|*secondary.RC.txt|*secondary.txt)
Meaning:
!(pattern-list)
Matches anything except one of the given patterns.
I would use an inverted grep match:
ls tRap* | grep -v "\.RC\." | grep -v "\.secondary\."
This should get rid of anything with ".RC." or ".secondary." in the title, which sounds like what you want.
This may not be the most elegant, but it works.

Piping find results into grep for fast directory exclusion

I am successfully using find to create a list of all files in the current subdirectory, excluding those in the subdirectory "cache." Here's my first bit of code:
find . -wholename './cach*' -prune -o -print
I now wish to pipe this into a grep command. It seems like that should be simple:
find . -wholename './cach*' -prune -o -print | xargs grep -r -R -i "samson"
... but this is returning results that are mostly from the cache directory. I've tried removing the xargs reference, but that does what you'd expect, running the grep on text of the file names, rather than on the files themselves. My goal is to find "samson" in any files that aren't cached content.
I'll probably get around this issue by just using doubled greps in this instance, but I'm very curious about why this one-liner behaves this way. I'd love to hear thoughts on a way to modify it while still using these two commands (as there are speed advantages to doing it this way).
(This is in CentOS 5, btw.)
The wholename match may be the reason why it's still including "cache" files. If you're executing the find command in the directory that contains the "cache" folder, it should work. If not, try changing it to -name '*cache*' instead.
Also, you do not need the -r or -R for your grep, that tells it to recurse through directories - but you're testing individual files.
You can update your command using the piped version, or a single-command:
find . -name '*cache*' -prune -o -print0 | xargs -0 grep -il "samson"
or
find . -name '*cache*' -prune -o -exec grep -iq "samson" {} \; -print
Note, the -l in the first command tells grep to "list the file" and not the line(s) that match. The -q in the second does the same; it tells grep to respond quietly so find will then just print the filename.
You've told grep itself to recurse (twice! -r and -R are synonyms). Since one of the arguments you're passing is . (the top directory), grep is searching in every file (some of them twice, or even more if they're in subdirectories).
If you're going to use find and grep, do this:
find . -path './cach*' -prune -o -print0 | xargs -0 grep -i "samson"
Using -print0 and -0 makes your script work even with file names that contain spaces or punctuation characters.
However, you probably don't need to bother with find here, since GNU grep is capable of excluding directories:
grep -R --exclude-dir='cach*' -i "samson" .
(This also excludes ./deeply/nested/directory/cache. If you only want to exclude cache directories at the toplevel, use find as you did.)
Use the -exec option on find instead of piping them to another command. From there you can use grep "samson" {} \; to look for samson in each file listed.
For example:
find . -wholename './cach*' -prune -o -exec grep "samson" "{}" +

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

How to list specific type of files in recursive directories in shell?

How can we find specific type of files i.e. doc pdf files present in nested directories.
command I tried:
$ ls -R | grep .doc
but if there is a file name like alok.doc.txt the command will display that too which is obviously not what I want. What command should I use instead?
If you are more confortable with "ls" and "grep", you can do what you want using a regular expression in the grep command (the ending '$' character indicates that .doc must be at the end of the line. That will exclude "file.doc.txt"):
ls -R |grep "\.doc$"
More information about using grep with regular expressions in the man.
ls command output is mainly intended for reading by humans. For advanced querying for automated processing, you should use more powerful find command:
find /path -type f \( -iname "*.doc" -o -iname "*.pdf" \)
As if you have bash 4.0++
#!/bin/bash
shopt -s globstar
shopt -s nullglob
for file in **/*.{pdf,doc}
do
echo "$file"
done
find . | grep "\.doc$"
This will show the path as well.
Some of the other methods that can be used:
echo *.{pdf,docx,jpeg}
stat -c %n * | grep 'pdf\|docx\|jpeg'
We had a similar question. We wanted a list - with paths - of all the config files in the etc directory. This worked:
find /etc -type f \( -iname "*.conf" \)
It gives a nice list of all the .conf file with their path. Output looks like:
/etc/conf/server.conf
But, we wanted to DO something with ALL those files, like grep those files to find a word, or setting, in all the files. So we use
find /etc -type f \( -iname "*.conf" \) -print0 | xargs -0 grep -Hi "ServerName"
to find via grep ALL the config files in /etc that contain a setting like "ServerName" Output looks like:
/etc/conf/server.conf: ServerName "default-118_11_170_172"
Hope you find it useful.
Sid
Similarly if you prefer using the wildcard character * (not quite like the regex suggestions) you can just use ls with both the -l flag to list one file per line (like grep) and the -R flag like you had. Then you can specify the files you want to search for with *.doc
I.E. Either
ls -l -R *.doc
or if you want it to list the files on fewer lines.
ls -R *.doc
If you have files with extensions that don't match the file type, you could use the file utility.
find $PWD -type f -exec file -N \{\} \; | grep "PDF document" | awk -F: '{print $1}'
Instead of $PWD you can use the directory you want to start the search in. file prints even out he PDF version.

What's the best way to find a string/regex match in files recursively? (UNIX)

I have had to do this several times, usually when trying to find in what files a variable or a function is used.
I remember using xargs with grep in the past to do this, but I am wondering if there are any easier ways.
grep -r REGEX .
Replace . with whatever directory you want to search from.
The portable method* of doing this is
find . -type f -print0 | xargs -0 grep pattern
-print0 tells find to use ASCII nuls as the separator and -0 tells xargs the same thing. If you don't use them you will get errors on files and directories that contain spaces in their names.
* as opposed to grep -r, grep -R, or grep --recursive which only work on some machines.
This is one of the cases for which I've started using ack (http://petdance.com/ack/) in lieu of grep. From the site, you can get instructions to install it as a Perl CPAN component, or you can get a self-contained version that can be installed without dealing with dependencies.
Besides the fact that it defaults to recursive searching, it allows you to use Perl-strength regular expressions, use regex's to choose files to search, etc. It has an impressive list of options. I recommend visiting the site and checking it out. I've found it extremely easy to use, and there are tips for integrating it with vi(m), emacs, and even TextMate if you use that.
If you're looking for a string match, use
fgrep -r pattern .
which is faster than using grep.
More about the subject here: http://www.mkssoftware.com/docs/man1/grep.1.asp
grep -r if you're using GNU grep, which comes with most Linux distros.
On most UNIXes it's not installed by default so try this instead:
find . -type f | xargs grep regex
If you use the zsh shell you can use
grep REGEX **/*
or
grep REGEX **/*.java
This can run out of steam if there are too many matching files.
The canonical way though is to use find with exec.
find . -name '*.java' -exec grep REGEX {} \;
or
find . -type f -exec grep REGEX {} \;
The 'type f' bit just means type of file and will match all files.
I suggest changing the answer to:
grep REGEX -r .
The -r switch doesn't indicate regular expression. It tells grep to recurse into the directory provided.
This is a great way to find the exact expression recursively with one or more file types:
find . \\( -name '\''*.java'\'' -o -name '\''*.xml'\'' \\) | xargs egrep
(internal single quotes)
Where
-name '\''*.<filetype>'\'' -o
(again single quotes here)
is repeated in the parenthesis ( ) for how many more filetypes you want to add to your recursive search
an alias looks like this in bash
alias fnd='find . \\( -name '\''*.java'\'' -o -name '\''*.xml'\'' \\) | xargs egrep'

Resources