grep - only get the prefix only - terminal

I know -h suppresses the prefix in grep so I would only get the filename. Is there a way to only get the prefix? I do a find for files and then pass that to grep.
Finally found it in the manual... -l looks like it now works

Not a flag, but how about
dirname
dirname /usr/bin/sort
/usr/bin

Related

How to get the grep command to search a specified directory?

I am trying to create a bash command that uses grep to search arguments in a specified directory. How would I do this. At the moment it only searches for the current directory. I have tried the following but it doesn't work:
ls $directoryName -l | grep "$1"
I'm sure there's a better way do do this but
ls -lah $directoryName > /usr/tmp/test
grep $1 /usr/tmp/test
rm /usr/tmp/test
Edit: You might have better luck using find though.
find $directoryName -name $1
Working example:
grep -e "Exec" /usr/share/applications/*
The following example will search recursively (including in sub-folders and hidden files) for an argument or pattern in a literal way (it will search for '$1' literally, not allowing substitution):
grep -re '$1' /folder/folder
Now, if you want to search for the value of the argument, then the code below would allow for substitution and do that:
grep -re "$1" /folder/folder

grep -l 'string' path prints the path followed by 'is a directory'

I have no idea what I'm doing wrong. I'm trying to get grep to return the string matches in files in a directory, but instead it is just returning the path followed by 'is a directory'. I looked in the man pages and did grep --help, but I do not understand the syntax.
You need -r for recursive.
The following will search through some_directory looking for files that contain something:
grep -l -r something some_directory
If you don't specify -r, grep thinks that you are trying to search the directory itself and it appropriately responds:
grep: some_directory: Is a directory
With -r, grep understands that you want to look for files in the directory tree starting with some_directory.
To retrieve file names without paths
To remove the paths from the file names, we can, for example, use basename:
grep --null -l -r something some_directory | xargs -0 -n1 basename
If you just want to eliminate some_directory while keeping any subdirectories, then use:
( cd some_directory; grep -l -r something . )

Finding all commands excluding "."

So far I have this:
ls /usr/bin | grep "^[\.]"
The cmd still gets files with a "." in there.
I have looked at [[:punct:]] but still returns the same thing.
There's grep -v to exclude things. So try
ls /usr/bin | grep -v \\.
man grep says
-v, --invert-match
Selected lines are those not matching any of the specified patterns.
It's generally considered a bad idea to parse ls.
If I understand you correctly, you want all files in /usr/bin that don't have a dot in the name. You can use find to do that:
find /usr/bin -not -name "*.*"
It is more portable (thanks #Adrian) to use a ! instead of -not:
find /usr/bin ! -name "*.*"
Not really clear, what you want:
your command:
ls /usr/bin | grep "^[\.]"
mean, filter the output from ls to show only files, what are start with a dot.
grep "^[\.]"
^ ^^ - escaped dot
+- at the begining of the line
If you want, exclude all files what contains dot, use
ls /usr/bin | grep -v '\.' #or see HenrikN's answer and comments (grep -vF .)
it you want exclude only entries what are starting with dot, use
grep '^[^\.]'
whats mean anything, but dot at the start
Ps: anyway, parsing output form ls is usually an very bad idea. (http://mywiki.wooledge.org/ParsingLs)
You can change your regex to exclude files starting with ".":
ls -a /usr/bin | grep "^[^.]"
This regex selects only files which do not have "." at the start. By the way only ls -a shows files that starts with ".". How did you manage to get them without "-a" ?
This can be achieved with pure bash, if the extglob shell option is enabled.
shopt -s extglob
echo /usr/bin/!(*.*)
# or alternatively:
echo /usr/bin/+([!.])
You may replace echo with ls -d if you want to pipe the list to another command line-wise.
I think you are referring to the current working directory and parent dirctory and not a command with "a dot" in it.
Try this as you probably have ls aliased:
/bin/ls /usr/bin

How do I get a list of all available shell commands

In a typical Linux shell (bash) it is possible to to hit tab twice, to get a list of all available shell commands.
Is there a command which has the same behaviour? I want to pipe it into grep and search it.
You could use compgen. For example:
compgen -c
You also could grep it, like this:
compgen -c | grep top$
Source: http://www.cyberciti.biz/open-source/command-line-hacks/compgen-linux-command/
You can list the directories straight from $PATH if you tweak the field separator first. The parens limit the effect to the one command, so use: (...) | grep ...
(IFS=': '; ls -1 $PATH)
"tab" twice & "y" prints all files in the paths of $PATH. So just printing all files in PATH is sufficient.
Just type this in the shell:
# printf "%s\n" ${PATH//:/\/* } > my_commands
This redirect all the commands to a file "my_commands".
List all the files in your PATH variable (ls all the directories in the PATH). The default user and system commands will be in /bin and /sbin respectively but on installing some software we will add them to some directory and link it using PATH variable.
There may be things on your path which aren't actually executable.
#!/bin/sh
for d in ${PATH//:/ }; do
for f in "$d"/*; do
test -x "$f" && echo -n "$f "
done
done
echo ""
This will also print paths, of course. If you only want unqualified filenames, it should be easy to adapt this.
Funny, StackOverflow doesn't know how to handle syntax highlighting for this. :-)
tabtaby
Similar to #ghoti, but using find:
#!/bin/sh
for d in ${PATH//:/ }; do
find $d -maxdepth 1 -type f -executable
done
Bash uses a builtin command named 'complete' to implement the tab feature.
I don't have the details to hand, but the should tell you all you need to know:
help complete
(IFS=':'; find $PATH -maxdepth 1 -type f -executable -exec basename {} \; | sort | uniq)
It doesn't include shell builtins though.
An answer got deleted, I liked it most, so I'm trying to repost it:
compgen is of course better
echo $PATH | tr ':' '\n' | xargs -n 1 ls -1
I found this to be the most typical shell thing, I think it works also with other shells (which I doubt with things like IFS=':' )
Clearly, there maybe problems, if the file is not an executable, but I think for my question, that is enough - I just want to grep my output - which means searching for some commands.

List files not matching a pattern?

Here's how one might list all files matching a pattern in bash:
ls *.jar
How to list the complement of a pattern? i.e. all files not matching *.jar?
Use egrep-style extended pattern matching.
ls !(*.jar)
This is available starting with bash-2.02-alpha1.
Must first be enabled with
shopt -s extglob
As of bash-4.1-alpha there is a config option to enable this by default.
ls | grep -v '\.jar$'
for instance.
Little known bash expansion rule:
ls !(*.jar)
With an appropriate version of find, you could do something like this, but it's a little overkill:
find . -maxdepth 1 ! -name '*.jar'
find finds files. The . argument specifies you want to start searching from ., i.e. the current directory. -maxdepth 1 tells it you only want to search one level deep, i.e. the current directory. ! -name '*.jar' looks for all files that don't match the regex *.jar.
Like I said, it's a little overkill for this application, but if you remove the -maxdepth 1, you can then recursively search for all non-jar files or what have you easily.
POSIX defines non-matching bracket expressions, so we can let the shell expand the file names for us.
ls *[!j][!a][!r]
This has some quirks though, but at least it is compatible with about any unix shell.
If your ls supports it (man ls) use the --hide=<PATTERN> option. In your case:
$> ls --hide=*.jar
No need to parse the output of ls (because it's very bad) and it scales to not showing multiple types of files. At some point I needed to see what non-source, non-object, non-libtool generated files were in a (cluttered) directory:
$> ls src --hide=*.{lo,c,h,o}
Worked like a charm.
Another approach can be using ls -I flag (Ignore-pattern).
ls -I '*.jar'
And if you want to exclude more than one file extension, separate them with a pipe |, like ls test/!(*.jar|*.bar). Let's try it:
$ mkdir test
$ touch test/1.jar test/1.bar test/1.foo
$ ls test/!(*.jar|*.bar)
test/1.foo
Looking at the other answers you might need to shopt -s extglob first.
One solution would be ls -1|grep -v '\.jar$'
Some mentioned variants of this form:
ls -d *.[!j][!a][!r]
But this seems to be only working on bash, while this seems to work on both bash and zsh:
ls -d *.[^j][^a][^r]
ls -I "*.jar"
-I, --ignore=PATTERN
do not list implied entries matching shell PATTERN
It works without having to execute anything before
It works also inside watch quotes: watch -d 'ls -I "*.gz"', unlike watch 'ls !(*.jar)' which produces: sh: 1: Syntax error: "(" unexpected
Note: For some reason in Centos requires quoting the pattern after -I while Ubuntu does not

Resources