I have this little command that delete all files within ~/Library/Cache, ~/Library/Logs, /Library/Cache and /Library/Logs directories but sometimes, one or more directories are missing and the rm -rf command is not execute.
sudo find ~/Library/Caches ~/Library/Logs /Library/Caches /Library/Logs -mindepth 1 -type f -exec rm -rf {}+
I wanted the command to ignore missing directories and just execute the command to the files that are found.
The only issue here is that you are annoyed with seeing the error message about missing directories.
You may redirect the standard error stream to /dev/null to ignore errors:
sudo find ~/Library/Caches ~/Library/Logs \
/Library/Caches /Library/Logs \
-mindepth 1 -type f -exec rm -rf {} + 2>/dev/null
Also note that -mindepth 1 is not needed here, and that some find implementations have -delete:
sudo find ~/Library/Caches ~/Library/Logs \
/Library/Caches /Library/Logs \
-type f -delete 2>/dev/null
Or, with a shell that understands brace expansions:
sudo find {~,}/Library/{Logs,Caches} -type f -delete 2>/dev/null
Related
I want this - https://stackoverflow.com/a/43561012/126833
find . -name 'node_modules' -type d -prune -exec rm -rf '{}'
except - instead of getting this done automatically, I want the all of the rm -rf /path/to/project/node_modules commands in a bash file like rm_node_modules.sh for me to review and then only I'll execute as bash rm_node_modules.sh
So basically my rm_node_modules.sh should be like :
rm -rf /path/to/project-1/node_modules
rm -rf /path/to/project-2/node_modules
rm -rf /path/to/project-3/node_modules
You are on macOS where find does not support the -printf flag which would make this a bit simpler. But something like this will do the job:
find . -name node_modules -type d -print0 | xargs -0 stat -f "rm -rf %N" > rm_node_modules.sh
I have a directory called "cdrs-roaming". Everyday I receive one or more .zip files and unzip them with this:
#!/bin/bash
for i in *.zip
do
j=${i//\.zip/}
mkdir $j
cd $j
unzip ../$i
cd -
done
Then I have for example:
"example1.zip" and "example1"; "example2.zip" and "example2"
I'm removing all zip files (in this case: "example1.zip" and "example2.zip") with this:
#! /bin/bash
find /dados/cdrs-roaming/*.zip -mtime +1 -exec rm {} \;
So I want to remove the directories (or folders - I really don't know the difference) "example1" and "example2". I've tried this:
#! /bin/bash
find /dados/cdrs-roaming/ -type d -mtime +1 -exec rm -rf {} \;
But it also removes "cdrs-roaming". I've also tried to use:
find /cdrs-roaming/ -type d -mtime +1 -exec rm -rf {} \;
But it returns: find: ‘/cdrs-roaming/’: No such file or directory
Any idea for doing this? I need to delete only the directories within "cdrs-roaming" but I can't remove anything else inside it (my .sh files are inside of it)
Since you are using bash, how about
rm -rf /dados/cdrs-roaming/*/
The final slash ensures that bash only expands the pattern to directories.
Use -mindepth 1 option:
find /dados/cdrs-roaming/ -mindepth 1 -type d -mtime +1 -exec rm -rf {} \;
I see that this question is getting popular.
I answered my own question below.
What says Inian is correct and it helped me to analyze my source code better.
My problem was in the FIND and not in the RM. My answer gives a block of code, which I am currently using, to avoid problems when FIND finds nothing but still would pass arguments to RM, causing the error mentioned above.
OLD QUESTION BELOW
I'm writing many and many different version of the same command.
All, are executed but with an error/info:
rm: missing operand
Try 'rm --help' for more information.
These are the commands I'm using:
#!/bin/bash
BDIR=/home/user/backup
find ${BDIR} -type d -mtime +180 -print -exec rm -rf {} \;
find ${BDIR} -type d -mtime +180 -print -exec rm -rf {} +
find "$BDIR" -type d -mtime +180 -print -exec rm -rf {} \;
find "$BDIR" -depth -type d -mtime +180 -print -exec rm -rf {} \;
find ${BDIR} -depth -type d -mtime +180 -print -exec rm -rf {} +
find $BDIR -type d -mtime +180 -print0 | xargs -0 rm -rf
DEL=$(FIND $BDIR -type d -mtime +180 -print)
rm -rf $DEL
I'm sure all of them are correct (because they all do their job), and if I run them manually I do not get that message back, but while in a .sh script I do.
EDIT: since I have many of these RM's, the problem could be somewhere else. I'm checking all of them. All of the above codes works but the best answer is the one marked ;)
The problem is when using find/grep along with xargs you need to be sure to run the piped command only if the previous command is successful. Like in the above case, if the find command does not produce any search results, the rm command is invoked with an empty argument list.
The man page of xargs
-r Compatibility with GNU xargs. The GNU version of xargs runs the
utility argument at least once, even if xargs input is empty, and
it supports a -r option to inhibit this behavior. The FreeBSD
version of xargs does not run the utility argument on empty
input, but it supports the -r option for command-line compatibil-
ity with GNU xargs, but the -r option does nothing in the FreeBSD
version of xargs.
Moreover, you don't to try all the commands like you pasted the below simple one will suit your need.
Add the -r argument to xargs like
find "$BDIR" -type d -mtime +180 -print0 | xargs -0 -r rm -rf
-f option of rm suppresses the rm: missing operand error:
-f, --force
ignore nonexistent files and arguments, never prompt
After researches, the command I'm comfortable using is:
HOME=/home/user
FDEL=$HOME/foldersToDelete
BDIR=/backup/my_old_folders
FLOG=/var/log/delete_old_backup.log
find ${BDIR} -mindepth 1 -daystart -type d -mtime +180 -printf "%f\n" > ${FDEL}
if [[ $? -eq 0 && $(wc -l < ${FDEL}) -gt 0 ]]; then
cd ${BDIR}
xargs -d '\n' -a ${FDEL} rm -rf
LOG=" - Folders older than 180 were deleted"
else
LOG=" - There aren't folders older than 180 days to delete"
fi
echo ${LOG} >> ${FLOG}
Why? I search all the old folders I want to delete and print them all into a file, regardless for their naming with or without space. If the file is bigger than 0 byte this means that there are folder I want no more.
If your 'FIND' fails with a 'rm: missing operand', it probably isn't to search in the RM rather in the FIND itself.
A good way of removing the file using FIND, is the one I felt to share with you.
I have a bash script that goes into a components/ and runs the following command:
cp -R vendor/* .
I then have a second command that traverses any folder, accept the vendor folder , inside the components directory lookinf got .git/, '.gitignore' and Documentation/ and removes them. How ever:
I don't thinks it's recursive
It doesn't actually remove those files and directories either because of the top point or because of permissions (should I add a sudo)?
A directory copied from vendor might look like:
something/
child-directory/
.git/ // -- Should be removed.
The command in question is:
find -name vendor -prune -o \( -name ".git" -o -name ".gitignore" -o -name "Documentation" \) -prune -exec rm - rf "{}" \; 2> /dev/null || true
Now if it is a permission error, I wont know about it because I want it to ignore any errors and continue with the script.
Any thoughts?
I think the problem is in the option -prune. Anyways, this might work for you...
find vendor -name '.git' -o -name '.gitignore' -o -name 'Documentation' | xargs rm -rf
I have directories named as:
2012-12-12
2012-10-12
2012-08-08
How would I delete the directories that are older than 10 days with a bash shell script?
This will do it recursively for you:
find /path/to/base/dir/* -type d -ctime +10 -exec rm -rf {} \;
Explanation:
find: the unix command for finding files / directories / links etc.
/path/to/base/dir: the directory to start your search in.
-type d: only find directories
-ctime +10: only consider the ones with modification time older than 10 days
-exec ... \;: for each such result found, do the following command in ...
rm -rf {}: recursively force remove the directory; the {} part is where the find result gets substituted into from the previous part.
Alternatively, use:
find /path/to/base/dir/* -type d -ctime +10 | xargs rm -rf
Which is a bit more efficient, because it amounts to:
rm -rf dir1 dir2 dir3 ...
as opposed to:
rm -rf dir1; rm -rf dir2; rm -rf dir3; ...
as in the -exec method.
With modern versions of find, you can replace the ; with + and it will do the equivalent of the xargs call for you, passing as many files as will fit on each exec system call:
find . -type d -ctime +10 -exec rm -rf {} +
If you want to delete all subdirectories under /path/to/base, for example
/path/to/base/dir1
/path/to/base/dir2
/path/to/base/dir3
but you don't want to delete the root /path/to/base, you have to add -mindepth 1 and -maxdepth 1 options, which will access only the subdirectories under /path/to/base
-mindepth 1 excludes the root /path/to/base from the matches.
-maxdepth 1 will ONLY match subdirectories immediately under /path/to/base such as /path/to/base/dir1, /path/to/base/dir2 and /path/to/base/dir3 but it will not list subdirectories of these in a recursive manner. So these example subdirectories will not be listed:
/path/to/base/dir1/dir1
/path/to/base/dir2/dir1
/path/to/base/dir3/dir1
and so forth.
So , to delete all the sub-directories under /path/to/base which are older than 10 days;
find /path/to/base -mindepth 1 -maxdepth 1 -type d -ctime +10 | xargs rm -rf
find supports -delete operation, so:
find /base/dir/* -ctime +10 -delete;
I think there's a catch that the files need to be 10+ days older too. Haven't tried, someone may confirm in comments.
The most voted solution here is missing -maxdepth 0 so it will call rm -rf for every subdirectory, after deleting it. That doesn't make sense, so I suggest:
find /base/dir/* -maxdepth 0 -type d -ctime +10 -exec rm -rf {} \;
The -delete solution above doesn't use -maxdepth 0 because find would complain the dir is not empty. Instead, it implies -depth and deletes from the bottom up.
I was struggling to get this right using the scripts provided above and some other scripts especially when files and folder names had newline or spaces.
Finally stumbled on tmpreaper and it has been worked pretty well for us so far.
tmpreaper -t 5d ~/Downloads
tmpreaper --protect '*.c' -t 5h ~/my_prg
Original Source link
Has features like test, which checks the directories recursively and lists them.
Ability to delete symlinks, files or directories and also the protection mode for a certain pattern while deleting
OR
rm -rf `find /path/to/base/dir/* -type d -mtime +10`
Updated, faster version of it:
find /path/to/base/dir/* -mtime +10 -print0 | xargs -0 rm -f