How to use 'find' to print only matching directories? - bash

I am trying to use find to recursively search the file names in a directory for a particular pattern (wp-config.*). When I do so using:
find `wp-config.*`
it seems to print all directories to the screen. How can I ensure that only the matching directories are printed to the screen?
Thanks.

From the answers in this outside post, I was able to use this command to do what I want:
find . -name 'wp-config.*' -printf "%h\n"
One of my main issues was that I originally did not understand that find does not print results to the screen. So it is necessary to pipe results to some kind of output.

Correct usage of find:
find -type d -name "wp-config.*"
The '-type d' will give you the directories.
The '-name "wp-config.*"' will give you the names requested.
Always use the man pages to search up commands. In this case:
man find
One last thing. The backticks ` are serving a totally different purpose. What you need here are regular quotes ".

Related

Exclude wildcard containing string 'x'

Is there a way to modify egrep -rha 'part1.*part2' to add something like: "if .* contains (not necessarily equals) string_x then pattern is not a match"? The problem is that string_x is present in every line so I can't -v it. It's okay to have this string before or after pattern, just not in the middle of it.
I'm assuming double .* with not string_x between them will get the job done, but it'll take a lot of time, plus I sometimes use .{n,m} wildcard, and in this case it would double the desired wildcard length. Maybe some sort of search termination every time it encounters string_x before part2?
Forget you ever heard about -r or any other option to let grep find files. There's a perfectly good tool for finding files with an extremely obvious name - find. Keep grep for what it's good at which is doing g/re/p. I can't imagine what the GNU guys were smoking when they decided to give grep options to find files, but hopefully they aren't now plotting to add options to sort files or pull content from web sites or print process data or do anything else that existing tools do perfectly well!
In this case you're looking for more than just g/re/p though so you should use awk:
awk '/part1.*part2/ && !/part1.*string_x.*part2/'
So the full script would be something like (untested since no sample input/output provided):
find . -type f -exec awk '/part1.*part2/ && !/part1.*string_x.*part2/' {} +

Passing the wildcard * unevaluated to inner commands

I'm writing a script that requires me to use an unevaluated *.
Here's what I've tried:
show() {
for file in $(find . -name $1); do
echo $file
done
}
If I run show *.pdf, the code will only look for PDFs in the current directory, and pass them into find . -name.
What I need is for the wildcard to be transferred to find unevaluated, so that it will look for PDFs recursively in the current folder.
My current solution involves doing this:
show() {
for file in $(find . -name "*$1"); do
echo $file
done
}
Which lets me write show .pdf, and that's fine, except nearly all bash commands that allow wildcards use the * operator. So for the sake of keeping it consistent with the rest of the system.
Is there a way for me to do this? I'm pulling my hairs out over this issue.
I've also tried show "*.pdf" but that yields the exact same result.
NOTE: It might look strange that I'm just echoing the result, when I could just have it run find . -name "*.pdf". That's true, but this is the first step in a larger script. I want to get this to work before continuing.

Python: Search for String in Filenames

I have been trying to search the root file system for a certain string (in the middle of the filename or wherever). I read about grep and I have tried this code here:
grep -rnw /home/pi/music -e "Maroon"
and something strange happens, there are three filenames with Maroon in them (same capitalization and spacing), but only two show up in the terminal. Any ideas why that is? Are there any other, easier ways to do this?
I would also like to say that I saw this StackOverflow post here, but I could not get it to work. I believe that was focusing on specific filenames, while I would like to do a general search.
All help is very much appreciated!
grep reads through the files on your disk, and searches for the word "Maroon".
What I think you want (when searching for file names) is:
find /home/pi/music -iname "*maroon*"
This will display all files that are named *maroon* (case insensitive). If you want case sensitive, take a look at -name.
man find
Will list all options for find.
The correct (or rather, the more common) way to search for files in matching a certain pattern is to use the find command, like this:
find /home/pi/music -type f -iname "*maroon*" -ls
type, limit searches to a particular type, in this case f for regular files (so it will ignore directories, pipes, sockets, etc.)
iname case insensitive name search
ls list the files found.
grep is used to search within files for matching content.
You want to use find to search for filenames
find /home/pi/music -depth 1 -name \*Maroon\*
This will find a file where the name contains the string. You need to quote the filename, so the shell doesn't glob it. -depth 1 so you only search the current directory

How to `ls` only one level deep?

I have lots subdirectories containing data, and I want a short list of which jobs (subdirectories) I have. I'm not happy with the following command.
$ ls H2*
H2a:
energy.dat overlap.dat
norm.dat zdip.dat ...
(much more)
H2b:
energy.dat overlap.dat
norm.dat zdip.dat ...
(much more)
This needless clutter defeats the purpose of the wildcard (limiting the output). How can I limit the output to one level deep? I'd like to see the following output
H2a/ H2b/ H2z/
Thanks for your help,
Nick
Try this
ls -d H2*/
The -d option is supposed to list "directories only", but by itself just lists
.
which I personally find kind of strange. The wildcard is needed to get an actual list of directories.
UPDATE: As #Philipp points out, you can do this even more concisely and without leaving bash by saying
echo H2*/
The difference is that ls will print the items on separate lines, which is often useful for piping to other functions.
You should consider using find, like this:
find . -maxdepth 1 -type d -name "H2*"
NOTE: Putting "-type d" before "-maxdepth 1" results in a warning on Debian Linux ("find: warning: you have specified the global option -maxdepth after the argument -type, but global options are not positional, i.e., -maxdepth affects tests specified before it as well as those specified after it. Please specify global options before other arguments.") No such warning is issued on Mac.
echo H2*
It's Bash who does the expansion, so you don't even need ls.
Should you have both files and directories starting with H2, you can append a slash to restrict the glob to directories:
echo H2*/
Perhaps this is what you are looking for?
ls | grep H2*
Use tree by Steve Baker at http://mama.indstate.edu/users/ice/tree/
It fills in for a lot of things that are missing from ls.
To list directories one layer deep:
tree -adi -L 1 H2*

Recursive grep for bash in cygwin

if i want an alias to do "rgrep pattern *" to search all files from my current location down through any sub directories, what is an alias for rgrep I can add to my bashrc file?
i would also like it to ignore errors and only report positive hits
In order for it to ignore errors (such as "Permission denied"), you'll probably need to use a function instead of an alias:
rgrep () { grep -r "${#}" 2>/dev/null; }
How about:
alias rgrep="grep -r"
This will only show 'positive hits', i.e. lines that contain the pattern you specify.
Small piece of advice, however: you might want to get used to just using grep -r directly. You'll then find it much easier if you ever need to use someone else's workstation, for instance!
Edit: you want to match patterns in file names, not in their contents (and also in directory names too). So how about this instead:
alias rgrep="find | grep"
By default, find will find all files and directories, so then it's just a case of passing that list to grep to find the pattern you're looking for.

Resources