How to find total size of all files under the ownership of a user? - linux

I'm trying to find out the total size of all files owned by a given user.
I've tried this:
find $myfolder -user $myuser -type f -exec du -ch {} +
But this gives me an error:
missing argument to exec
and I don't know how to fix it. Can somebody can help me with this?

You just need to terminate the -exec. If you want the totals for each directory
possibly -type d is required.
find $myfolder -user $myuser -type d -exec du -ch {} \;

Use:
find $myfolder -user gisi -type f -print0 | xargs -0 du -sh
where user gisi is my cat ;)
Note the option -s for summarize
Further note that I'm using find ... -print0 which on the one hand separates filenames by 0 bytes, which are one of the few characters which are not allowed in filenames, and on the other hand xargs -0 which uses the 0 byte as the delimiter. This makes sure that even exotic filenames won't be a problem.

some version of find command does not like "+" for termination of find command
use "\;" instead of "+"

Related

Write a script that deletes all the regular files (not the directories) with a .js extension that are present in the current directory and all its sub [duplicate]

I'm trying to work out a command which deletes sql files older than 15 days.
The find part is working but not the rm.
rm -f | find -L /usr/www2/bar/htdocs/foo/rsync/httpdocs/db_backups -type f \( -name '*.sql' \) -mtime +15
It kicks out a list of exactly the files I want deleted but is not deleting them. The paths are correct.
usage: rm [-f | -i] [-dIPRrvW] file ...
unlink file
/usr/www2/bar/htdocs/foo/rsync/httpdocs/db_backups/20120601.backup.sql
...
/usr/www2/bar/htdocs/foo/rsync/httpdocs/db_backups/20120610.backup.sql
What am I doing wrong?
You are actually piping rm's output to the input of find. What you want is to use the output of find as arguments to rm:
find -type f -name '*.sql' -mtime +15 | xargs rm
xargs is the command that "converts" its standard input into arguments of another program, or, as they more accurately put it on the man page,
build and execute command lines from standard input
Note that if file names can contain whitespace characters, you should correct for that:
find -type f -name '*.sql' -mtime +15 -print0 | xargs -0 rm
But actually, find has a shortcut for this: the -delete option:
find -type f -name '*.sql' -mtime +15 -delete
Please be aware of the following warnings in man find:
Warnings: Don't forget that the find command line is evaluated
as an expression, so putting -delete first will make find try to
delete everything below the starting points you specified. When
testing a find command line that you later intend to use with
-delete, you should explicitly specify -depth in order to avoid
later surprises. Because -delete implies -depth, you cannot
usefully use -prune and -delete together.
P.S. Note that piping directly to rm isn't an option, because rm doesn't expect filenames on standard input. What you are currently doing is piping them backwards.
find /usr/www/bar/htdocs -mtime +15 -exec rm {} \;
Will select files in /usr/www/bar/htdocs older than 15 days and remove them.
Another simpler method is to use locate command. Then, pipe the result to xargs.
For example,
locate file | xargs rm
Use xargs to pass arguments, with the option -rd '\n' to ignore spaces in names:
"${command}" | xargs -rd '\n' rm
Include --force if you want to also remove read only files.
Assuming you aren't in the directory containing the *.sql backup files:
find /usr/www2/bar/htdocs/foo/rsync/httpdocs/db_backups/*.sql -mtime +15 -exec rm -v {} \;
The -v option above is handy it will verbosely output which files are being deleted as they are removed.
I like to list the files that will be deleted first to be sure. E.g:
find /usr/www2/bar/htdocs/foo/rsync/httpdocs/db_backups/*.sql -mtime +15 -exec ls -lrth {} \;

delete old files in a directory

okay maybe this sounds simple, but it has been a bit challenging to me
I have a directory called backups and it has (backup files + other files)
backups files:
../backups/backup-2013_03_03.zip
../backups/backup-2013_03_05.zip
../backups/backup-2013_01_01.zip
../backups/backup-2013_08_16.zip
../backups/backup-2013_02_28.zip
../backups/backup-2013_01_21.zip
../backups/backup-2013_03_29.zip
../backups/backup-2013_04_05.zip
I'm trying to delete backup files older than 90 days.
find /var/tmp/stuff -mtime +90 -print | xargs /bin/rm
seems to work, but I'm not able to limit the search to backup files only. "files which starts with backup*"
I have tried adding "-iname backup" option to find command argument, thinking it would do the trick but it doesn't seems to work.
Any ideas?
Thank you
You can pipe through grep before calling rm. Something like:
find /var/tmp/stuff -mtime +90 -print | grep 'backup-' | xargs /bin/rm
while the find utility has all kinds of options to single handedly do this, including the deleting as noted in other answers, I can never remember any but the most basic options.
find "stuff" | grep "some_other_stuff" | xargs "do_stuff"
seems much easier to remember for me.
The parameter to iname matches against the full filename, so you need a trailing wildcard:
find /var/tmp/stuff -mtime +90 -iname "backup*" -print | xargs /bin/rm
You could also use find's -exec argument, but personally I find the syntax quite arcane. I prefer xargs.
find /var/tmp/stuff -mtime +90 -iname "backup*" -exec /bin/rm '{}'
Or, as damienfrancois points out, GNU find can take a -delete argument. This is the best solution because a) it is shorter and b) it is more efficient because the deletion happens within the find process. exec and xargs will both spawn one new process per file to delete. Source: GNU manual However, as wildplasser points out, it could also be dangerous - -delete will remove directories by default. To only delete files, use -type f.
find /var/tmp/stuff -type f -mtime +90 -iname "backup*" -delete
You could use -exec option of find along with -iname. Since you want to delete only files, you would need to specify -type f
find /var/tmp/stuff -type f -iname 'backup*' -mtime +90 -exec rm {} +
If you prefer xargs like me
find /var/tmp/stuff -type f -iname 'backup*' -mtime +90 -print0 | xargs -0 rm
Note : It's recommended to use find -print0 with xargs -0 to avoid weird file name caveats

calculate total used disk space by files older than 180 days using find

I am trying to find the total disk space used by files older than 180 days in a particular directory. This is what I'm using:
find . -mtime +180 -exec du -sh {} \;
but the above is quiet evidently giving me disk space used by every file that is found. I want only the total added disk space used by the files. Can this be done using find and exec command ?
Please note I simply don't want to use a script for this, it will be great if there could be a one liner for this. Any help is highly appreciated.
Why not this?
find /path/to/search/in -type f -mtime +180 -print0 | du -hc --files0-from - | tail -n 1
#PeterT is right. Almost all these answers invoke a command (du) for each file, which is very resource intensive and slow and unnecessary. The simplest and fastest way is this:
find . -type f -mtime +356 -printf '%s\n' | awk '{total=total+$1}END{print total/1024}'
du wouldn't summarize if you pass a list of files to it.
Instead, pipe the output to cut and let awk sum it up. So you can say:
find . -mtime +180 -exec du -ks {} \; | cut -f1 | awk '{total=total+$1}END{print total/1024}'
Note that the option -h to display the result in human-readable format has been replaced by -k which is equivalent to block size of 1K. The result is presented in MB (see total/1024 above).
Be careful not to take into account the disk usage by the directories. For example, I have a lot of files in my ~/tmp directory:
$ du -sh ~/tmp
3,7G /home/rpet/tmp
Running the first part of example posted by devnull to find the files modified in the last 24 hours, we can see that awk will sum the whole disk usage of the ~/tmp directory:
$ find ~/tmp -mtime 0 -exec du -ks {} \; | cut -f1
3849848
84
80
But there is only one file modified in that period of time, with very little disk usage:
$ find ~/tmp -mtime 0
/home/rpet/tmp
/home/rpet/tmp/kk
/home/rpet/tmp/kk/test.png
$ du -sh ~/tmp/kk
84K /home/rpet/tmp/kk
So we need to take into account only the files and exclude the directories:
$ find ~/tmp -type f -mtime 0 -exec du -ks {} \; | cut -f1 | awk '{total=total+$1}END{print total/1024}'
0.078125
You can also specify date ranges using the -newermt parameter. For example:
$ find . -type f -newermt "2014-01-01" ! -newermt "2014-06-01"
See http://www.commandlinefu.com/commands/view/8721/find-files-in-a-date-range
You can print file size with find using the -printf option, but you still need awk to sum.
For example, total size of all files older than 365 days:
find . -type f -mtime +356 -printf '%s\n' \
| awk '{a+=$1;} END {printf "%.1f GB\n", a/2**30;}'

Find all files matching 'name' on linux system, and search with them for 'text'

I need to find all instances of 'filename.ext' on a linux system and see which ones contain the text 'lookingfor'.
Is there a set of linux command line operations that would work?
find / -type f -name filename.ext -exec grep -l 'lookingfor' {} +
Using a + to terminate the command is more efficient than \; because find sends a whole batch of files to grep instead of sending them one by one. This avoids a fork/exec for each single file which is found.
A while ago I did some testing to compare the performance of xargs vs {} + vs {} \; and I found that {} + was faster. Here are some of my results:
time find . -name "*20090430*" -exec touch {} +
real 0m31.98s
user 0m0.06s
sys 0m0.49s
time find . -name "*20090430*" | xargs touch
real 1m8.81s
user 0m0.13s
sys 0m1.07s
time find . -name "*20090430*" -exec touch {} \;
real 1m42.53s
user 0m0.17s
sys 0m2.42s
Go to respective directory and type the following command.
find . -name "*.ext" | xargs grep
'lookingfor'
A more simple one would be,
find / -type f -name filename.ext -print0 | xargs -0 grep 'lookingfor'
-print0 to find & 0 to xargs would mitigate the issue of large number of files in a single directory.
Try:
find / -type f -name filename.ext -exec grep -H -n 'lookingfor' {} \;
find searches recursively starting from the root / for files named filename.ext and for every found occurrence it runs grep on the file name searching for lookingfor and if found prints the line number (-n) and the file name (-H).
I find the following command the simplest way:
grep -R --include="filename.ext" lookingfor
or add -i to search case insensitive:
grep -i -R --include="filename.ext" lookingfor

Linux command for removing all ~ files

What command can I use in Linux to check if there is a file in a given directory (or its subdirectories) that contains a ~at the end of the file's name?
For example, if I'm at a directory called t which contains many subdirectories, etc, I would like to remove all files that end with a ~.
Watch out for filenames with spaces in them!
find ./ -name "*~" -type f -print0 | xargs -0 rm
with GNU find
find /path -type f -name "*~" -exec rm {} +
or
find /path -type f -name "*~" -delete
find ./ -name '*~' -print0 | xargs -0 rm -f
Here find will search the directory ./ and all sub directories, filtering for filenames that match the glob '*~' and printing them (with proper quoting courtesy of alberge). The results are passed to xargs to be appended to rm -f and the resulting string run in a shell. You can use multiple paths, and there are many other filters available (just read man find).
you can use a find, grep, rm combination, something like
find | grep "~" | xargs rm -f
Probably others have better ideas :)

Resources