Python: Search for String in Filenames - shell

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

Related

Use grep to exactly match a string in text inside files and then move those files to a separate directory

I have several files inside a directory, some which contain the word "sweet". I would like to use grep to find the files which contain the exact word and then move them to a different folder.
This is my code :
mv `grep -lir 'sweet' ~/directory1/` ~/directory2
However, there are some files with the word "sweets" or "sweeter" or "Sweet", my command is moving them as well, whereas I want the match to be strictly "sweet".
Please help, thanks.
Using grep -lrwF works
check comment thread with Shawn

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/' {} +

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

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 ".

Using bash to list files with a certain combination of characters

So I have a directory with ~50 files, and each contain different things. I often find myself not remembering which files contain what. (This is not a problem with the naming -- it is sort of like having a list of programs and not remembering which files contain conditionals).
Anyways, so far, I've been using
cat * | grep "desiredString"
for a string that I know is in there. However, this just gives me the lines which contain the desired string. This is usually enough, but I'd like it to give me the file names instead, if at all possible.
How could I go about doing this?
It sounds like you want grep -l, which will list the files that contain a particular string. You can also just pass the filename arguments directly to grep and skip cat.
grep -l "desiredString" *
In the directory containing the files among which you want to search:
grep -rn "desiredString" .
This can list all the files matching "desiredString", with file names, matching lines and line numbers.

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*

Resources