Bash list directories that matches pattern, not children of them - linux

I have a folder ~/anna which contains the file ~/anna/b
When I type ls ~/a* I get b.
How can I retrieve ~/anna ?
The script for recreating the scenatrio:
cd ~/
mkdir anna
touch anna/b
ls ~/a*
Expected result: anna
Actually result: b
Thanks!

To get help for the ls, just ask for it:
ls --help
You'll get list of useful options for the ls command, one of them:
-d, --directory list directory entries instead of contents,
and do not dereference symbolic links
So the solution (as stated in comments) would be:
ls -d ~/a*

Depending on your different requirements, find might be more appropriate:
find ~/ -name "a*" -type d
or
find ~/ -mindepth 1 -maxdepth 1 -name "a*" -type d
explanation:
~/: search in home dir
-mindepth 1 -maxdepth 1: only directories "one deep"
-name "a*": all files or folders starting with a
-type d: find only directories

Related

Use Linux Find to search for directories that contain a file with properties

I'm trying to find projects in an enormous directory. The projects are always several levels of depth in and have a config file which contains the project name. So basically...
Given a path and string
Return any directory that has a depth of 3 from the and contains a file named "config"
that contains the
I learned that find combined with grep will work... but print out the grepped text and not the path of it's parent directory
find <starting-dir> -maxdepth 3 -mindepth 3 -type d -exec grep '<project-name>' {}/config \;
Just prints out the project name :(
Perhaps there any way to switch back to find's default behaviour of printing out the found file path only if the grep is successful? Or is there another tool I should try to use to solve this?
To get -print, you need to add it explicitly after a succesful -exec.
For example, using grep's -q:
find <starting-dir> \
-maxdepth 3 -mindepth 3 \
-type d \
-exec grep -q '<project-name>' {}/config \; \
-print
As you discovered, grep already has -l.
You can reduce the number of grep processes:
find <starting-dir> \
-maxdepth 4 -mindepth 4 \
-type f -name config \
-exec grep -l '<project-name>' {} +
Adding the -l flag to my output fixes the issue, for some reason I thought that would just print out "config" and not the whole path of that config file, but here we are.
find <starting-dir> -maxdepth 3 -mindepth 3 -type d -exec grep -l '<project-name>' {}/config \;
This will print out the full path of the config file of the project you search for.

See if directory rec is used as symlink in Linux

I want to see, if a symlink points to a directories in a specific dir - recursively.
Of course, I clould use
find / -type l -ls 2>/dev/null |grep /targetpath
But I do not want type all the (recurse) paths.
So I put all symlinks on my system into a file once.
find / -type l -ls 2>/dev/null >~/symlinks.txt
Then I list the directories recursively.
find /targetpath to start/ -maxdepth 2 -type d
And that is my question:
Can I pipe these paths from the last command to grep?
Grep should look into my file symlinks.txt and show the linecontent of matching lines (could be more symlinks pointing to this DIR)
I tried something like
find /targetpath to stat/ -maxdepth 2 -type d | xargs -0 -ifoo grep foo symlinks.txt
But it does not do, what I expect.
Or maybe an other, better solution?
From man find:
-lname pattern
File is a symbolic link whose contents match shell pattern pattern. [...]
Try:
find / -lname '*/targetpath/*'
See find-all-symlinks-to-a-directory-and-change-target-to-another-directory.

Show only directories, not their contents with `find -type d | xargs ls`

I want to find some folders by name, and then list their information using "ls", here is what i did using "find",
find ./ -mindepth 1 -maxdepth 3 -type d -name logs
what i got is:
./RECHMN32Z/US/logs
./RECHMN32Z/UM/logs
./RECHMP3BL/US/logs
./RECHMP3BL/UM/logs
./RECHMAS86/UM/logs
./RECHMAS86/US/logs
and then i add "xargs ls -l" , then it will return information of all files under these folders returned above,
if i just want to list information of these folders, how to do ?
It's not find or xargs's fault, but ls's. When given directory names ls shows their contents. You can use -d to have it only show the directories themselves.
find has a -ls action that uses the same format as ls -dils. No need to invoke an external command.
find ./ -mindepth 1 -maxdepth 3 -type d -name logs -ls
Or use ls -ld to list the directories and not their contents. -exec cmd {} + is a simpler alternative to xargs. No pipeline required.
find ./ -mindepth 1 -maxdepth 3 -type d -name logs -exec ls -ld {} +

find folders in a directory, without listing the parent directory

Having trouble listing the contents of a folder I'm not in, while excluding the actual folder name itself.
ex:
root#vps [~]# find ~/test -type d
/root/test
/root/test/test1
However I want it to only display /test1, as the example.
Thoughts?
There's nothing wrong with a simple
find ~/test -mindepth 1
Similarly, this will have the same effect:
find ~/test/*
as it matches everything contained within ~/test/ but not ~/test itself.
As an aside, you'll almost certainly find that find will complain about the -mindepth n option being after any other switches, as ordering is normally important but the -(min|max)depth n switches affect overall behaviour.
You can do that with -exec and basename:
find ~/test -type d -exec basename {} \;
Explanation:
The find ~/test -type d part finds all directories recursively under ~/test, as you already know.
The -exec basename {} \; part runs the basename command on {}, which is where all the results from the last step are substituted into.
Then you need -type f instead of -type d.
Or, if you want to display list of folders, excluding the parent -mindepth 1 (find ~/test -type d -mindepth 1).
And now that you edited it, I think what you want may be
find ~/test -type d -mindepth 1 |cut -d/ -f3-
But I think you need to be more specific ;-)
I just fixed it with sed
find $BASE -type d \( ! -iname "." \)|sed s/$BASE//g
Where $BASE is initial foldername.

Remove a bunch of directories from one location based on a list of directories in another location?

I have two directories in totally different places in the filesystem:
/path1/dir1/*
/path2/dir2/*
dir1 has a list of subdirectories and dir2 has a similar list of subdirectories, some of which are also in dir1
I'd like a command that can use a list of the subdirectories that are currently in dir1 and if they exist in dir2, delete them.
I was able to output a list of the subdirectory names using the find command and sed together like this:
find $PWD -maxdepth 1 -type d | sed -e 's\^/path1/dir1///g' and that will output:
subdir1
subdir2
subdir3
but I don't know how to then feed that into a command to delete (recursively) those subdirectories from another location. Do I need to use awk or xargs or something?
Sounds like you want something like this:
cd /path1/dir1; find . -type d -maxdepth 1 -mindepth 1 -exec rm -rf /path2/dir2/{} \;
Replace the "rm -rf" with "echo" to see what directories it will delete before trying it :-)
The "-f" option prevents errors if the directory doesn't exist
Some versions of find (GNU?) also have "-execdir". You can use it like this:
find /path1/dir -type d -maxdepth 1 -mindepth 1 -execdir rm -rf /path2/dir2/{} \;
for dir in path1/dir1/*/
do
rm -rf path2/dir2/"$(basename dir)"
done
You could also try using find to locate the dirs and piping to awk:
find /path1/dir1/ -maxdepth 1 -mindepth 1 -type d |awk 'BEGIN{FS="/"}{system("echo rm -rf /path2/dir2/"$NF);}'
remove the "echo" in the system() call when you are sure the command is behaving properly.

Resources