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

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)

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 {} \;

Delete all directories excluding a specific one

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.

Deleting multiple files in Linux?

How can I delete multiple files in Linux created at same date and time? How can I manage this without using date? The file have different names.
I have these .txt files:
-rw-r--r-- 1 root root 54 Jan 6 17:28 file1.txt
-rw-r--r-- 1 root root 33 Jan 6 17:28 file2.txt
-rw-r--r-- 1 root root 24 Jan 6 18:05 file3.txt
-rw-r--r-- 1 root root 0 Jan 6 17:28 file4.txt
-rw-r--r-- 1 root root 0 Jan 6 17:28 file5.txt
How can I delete all the files with one command?
You can use find command and specify the time range. In your example: if you would like to find all files with modified timestamp from 6. Jan 17:28 you can do something like:
find . -type f -newermt '2016-01-06 17:28' ! -newermt '2016-01-06 17:29'
if you would like to delete them, just use finds exec parameter:
find . -type f -newermt '2016-01-06 17:28' ! -newermt '2016-01-06 17:29' -exec rm {} \;
you can also include -name '*.txt' if you want to process only *.txt files, and check maxdepth parameter as well if you would like to avoid processing subdirectories
simply use rm -f file*.txt to delete all files which starts with file and ends with the extention .txt
If you know the minutes of the file modified then you can deleted all files using find command. consider the file was last modified ten minutes ago. Then you can use,
find -iname "*.txt" -mmin 10 -ok rm {} \;
If you don't need to prompt before deleting then use -exec.
find -iname "*.txt" -mmin 10 -exec rm {} \;
If you need to delete the files using access time then you can use -amin

How can I list files modified within a directory yesterday via command line?

I'd like to list out all files with modification dates in the last n days (or even simply after Y-m-d) in a directory. It must work recursively through all subdirectories as well.
How can I do this?
Ideal output:
file.txt Mar 26 15:15
file2.txt Mar 27 01:15
Acceptable output:
file.txt
file2.txt
Answered! (Thanks for all the help)
$ find . -type f -mtime -1 -exec ls -lah {} \;
-rw-r--rw- 1 apache apache 18K Mar 26 08:22 ./file1.txt
-rw-r--rw- 1 apache apache 12K Mar 26 09:23 ./dir1/file2.txt
-rw-r--rw- 1 apache apache 16K Mar 26 10:24 ./dir1/dir2/file3.txt
find . -type f -mtime -1 -exec ls -l {} \;
will list all files within last 24 hours, with a long listing just to confirm modification date
use :
find . -mtime +1
For more informations, see
man find
find dir -mtime +1 -print
That will find all files in dir and subdirectories that were modified 1 day ago or before that.

Find all writable files in the current directory

I want to quickly identify all writable files in the directory. What is the quick way to do it?
find -type f -maxdepth 1 -writable
The -writable option will find files that are writable by the current user. If you'd like to find files that are writable by anyone (or even other combinations), you can use the -perm option:
find -maxdepth 1 -type f -perm /222
This will find files that are writable by their owner (whoever that may be):
find -maxdepth 1 -type f -perm /200
Various characters can be used to control the meaning of the mode argument:
/ - any permission bit
- - all bits (-222 would mean all - user, group and other)
no prefix - exact specification (222 would mean no permssions other than write)
to find writable files regardless of owner, group or others, you can check the w flag in the file permission column of ls.
ls -l | awk '$1 ~ /^.*w.*/'
$1 is the first field, (ie the permission block of ls -l) , the regular expression just say find the letter "w" in field one. that's all.
if you want to find owner write permission
ls -l | awk '$1 ~ /^..w/'
if you want to find group write permission
ls -l | awk '$1 ~ /^.....w/'
if you want to find others write permission
ls -l | awk '$1 ~ /w.$/'
-f will test for a file
-w will test whether it's writeable
Example:
$ for f in *; do [ -f $f ] && [ -w $f ] && echo $f; done
If you are in shell use
find . -maxdepth 1 -type f -writable
see man find
You will find you get better answers for this type of question on superuser.com or serverfault.com
If you are writing code not just using shell you may be interested in the access(2) system call.
This question has already been asked on serverfault
EDIT: #ghostdog74 asked if you removed write permissions for this file if this would still find the file. The answer, no this only finds files that are writable.
dwaters#eirene ~/temp
$ cd temp
dwaters#eirene ~/temp/temp
$ ls
dwaters#eirene ~/temp/temp
$ touch newfile
dwaters#eirene ~/temp/temp
$ ls -alph
total 0
drwxr-xr-x+ 2 dwaters Domain Users 0 Mar 22 13:27 ./
drwxrwxrwx+ 3 dwaters Domain Users 0 Mar 22 13:26 ../
-rw-r--r-- 1 dwaters Domain Users 0 Mar 22 13:27 newfile
dwaters#eirene ~/temp/temp
$ find . -maxdepth 1 -type f -writable
./newfile
dwaters#eirene ~/temp/temp
$ chmod 000 newfile
dwaters#eirene ~/temp/temp
$ ls -alph
total 0
drwxr-xr-x+ 2 dwaters Domain Users 0 Mar 22 13:27 ./
drwxrwxrwx+ 3 dwaters Domain Users 0 Mar 22 13:26 ../
---------- 1 dwaters Domain Users 0 Mar 22 13:27 newfile
dwaters#eirene ~/temp/temp
$ find . -maxdepth 1 -type f -writable
dwaters#eirene ~/temp/temp
for var in `ls`
do
if [ -f $var -a -w $var ]
then
echo "$var having write permission";
else
echo "$var not having write permission";
fi
done
The problem with find -writable is that it's not portable and it's not easy to emulate correctly with portable find operators. If your version of find doesn't have it, you can use touch to check if the file can be written to, using -r to make sure you (almost) don't modify the file:
find . -type f | while read f; do touch -r "$f" "$f" && echo "File $f is writable"; done
The -r option for touch is in POSIX, so it can be considered portable. Of course, this will be much less efficient than find -writable.
Note that touch -r will update each file's ctime (time of last change to its meta-data), but one rarely cares about ctime anyway.
Find files writeable by owner:
find ./ -perm /u+w
Find files writeable by group:
find ./ -perm /g+w
Find files writeable by anyone:
find ./ -perm /o+w
Find files with defined permission:
find ./ -type -d -perm 0777
find ./ -type -d -perm 0755
find ./ -type -f -perm 0666
find ./ -type -f -perm 0644
Disable recursive with:
-maxdepth 1
stat -c "%A->%n" *| sed -n '/^.*w.*/p'
I know this a very old thread, however...
The below command helped me: find . -type f -perm /+w
You can use -maxdepth based on how many levels below directory you want to search.
I am using Linux 2.6.18-371.4.1.el5.
If you want to find all files that are writable by apache etal then you can do this:
sudo su www-data
find . -writable 2>/dev/null
Replace www-data with nobody or apache or whatever your web user is.

Resources