Delete all directories excluding a specific one - linux

On a linux host, given an absolute path, I want to delete all except a certain directory.
To simplify things below is the directory structure and I want to delete all directories except test2
[root#hostname test]# pwd
/opt/data/test
root#hostname test]# ls -ltr
total 8
drwxr-xr-x 5 root root 4096 Dec 5 09:33 test1
drwxr-xr-x 2 root root 4096 Dec 5 09:44 test2
[root#hostname test]#
I looked into How to exclude a directory in find . command and tried the prune switch like this
[root#hostname test]# find /opt/data/test -type d -path test2 -prune
-o ! -name "test2" -print
/opt/data/test
/opt/data/test/test1
/opt/data/test/test1/ls.txt
/opt/data/test/test1/test13
/opt/data/test/test1/test13/temp.py
/opt/data/test/test1/test13/try.pl
/opt/data/test/test1/test11
/opt/data/test/test1/test11/ls.txt
/opt/data/test/test1/test11/temp.py
/opt/data/test/test1/test11/try.pl
/opt/data/test/test1/test12
/opt/data/test/test1/test12/ls.txt
/opt/data/test/test1/test12/temp.py
/opt/data/test/test1/test12/try.pl
/opt/data/test/test1/temp.py
/opt/data/test/test1/try.pl
/opt/data/test/test2/ls.txt
/opt/data/test/test2/temp.py
/opt/data/test/test2/try.pl
[root#hostname test]
now it lists all the folder including /opt/data/test and if I add the xargs rm -rf to this, it will delete the parent folder as well. I don't think I understood the concept -path and -name correctly, please help

Using a simple negation with -not may be easier than pruning:
$ find /opt/data/test -type d -not -name test2
EDIT:
There's no reason to recurse in to the subdirectories, since you're going to delete the top directories anyway, so you could add -maxdepth and avoid finding the directories inside test2:
$ find /opt/data/test -maxdepth 1 -type d -not -name test2

I was able to achieve the required behavior by adding -mindepth 1 to the find command to exclude the parent directory.

Related

printing directory with simple ls and grep command Linux

So I have this command ls -al -R | grep libbpf.h and it just act dump print
-rw-r--r-- 1 root root 53107 جنوری 27 12:05 libbpf.h
I also need the exact subdirectories that contain this file is there a way I can use the above command with some option for grep or ls so it also prints some thining like
-rw-r--r-- 1 root root ./libbpf/src/include/libbpf.h 53107 جنوری 27 12:05 libbpf.h
so I only knows the the libbpf.h does exists in somewhere from root directory recursively searching just give me the path, does any one knows this
you can use find command
find "$(pwd -P)" -type f -name "libbpf.h" -ls
if you want only paths
find "$(pwd -P)" -type f -name "libbpf.h"
or
find . -type f -name "libbpf.h" -exec realpath {} \;

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

How to remove all files that are empty in a directory?

Suppose I've got a directory that looks like:
-rw-r--r-- 1 some-user wheel 0 file1
-rw-r--r-- 1 some-user wheel 257 file2
-rw-r--r-- 1 some-user wheel 0 file3
-rwxr-xr-x 1 some-user wheel 212 file4
-rw-r--r-- 1 some-user wheel 2012 file5
.... more files here.
If it's relevant, assume that the names of the files are more random than just file#.
How do I remove only the files that are empty (meaning that the file has 0 bytes in it) in a directory, using rm and grep or sed in some form?
The easiest way is to run find with -empty test and -delete action, e.g.:
find -type f -empty -delete
The command finds all files (-type f) in the current directory and its subdirectories, tests if the matched files are empty, and applies -delete action, if -empty returns true.
If you want to restrict the operation to specific levels of depth, use -mindepth and -maxdepth global options.
The command is:
cd DirectoryWithTheFiles
rm -f $(find . -size 0)

Bash list directories that matches pattern, not children of them

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

Deleting a directory starting with a specific string in shell script

When I'm trying to delete all directories starting with tmp,
I used this command:
find -type d -name tmp* -exec rmdir {} \;
And it does the trick, but this command is exiting with an error code:
find: `./tmp09098': No such file or directory
What causing failing my build.
Can anyone tell me how I can delete those folders without getting the error?
After trying what #anubhava suggested and quoted 'temp*',
find -type d -name 'tmp*' -exec rmdir {} \;
I still get the same error:
find: `./tmp0909565g': No such file or directory
find: `./tmp09095': No such file or directory
When running:
find -type d -name 'tmp*' -exec ls -ld '{}' \;
This is the result:
drwxr-xr-x 2 root root 4096 Jun 16 10:08 ./tmp0909565g
drwxr-xr-x 2 root root 4096 Jun 16 10:07 ./tmp09095
drwxr-xr-x 2 root root 4096 Jun 16 10:08 ./tmp09094544656
You should quote the pattern otherwise it will be expanded by shell on command line:
find . -type d -name 'tmp*' -mindepth 1 -exec rm -rf '{}' \; -prune
-prune causes find to not descend into the current file/dir.
This works for me:
#! /bin/bash
tmpdirs=`find . -type d -name "tmp*"`
echo "$tmpdirs" |
while read dir;
do
echo "Removing directory $dir"
rm -r $dir;
done;

Resources