I have this command to run in Unix machine where I'm deleting all directories from specific folder if they are older then 1 day:
find /path_with_dirs_to_delete/* -type d -mtime +1 -prune -exec rm -rf {} + -print
It's currently printing out the folder names and i want to concatenate to the printing output the text " was deleted successfully".
How can I do that?
If using GNU tools, a superior solution is to add the -v (verbose) flag to rm.
For a POSIX solution you could do this:
find /path/* -type d -mtime +1 -prune -exec rm -rf {} \; -exec echo {} was deleted successfully \;
You were running a single rm to remove multiple directories. But if you want to test rm's success for each directory, it has to run once per directory (note ; instead of +). Note that this a bit less efficient.
-a ("and") is implied between find actions, meaning the second -exec action (echo) only runs if the previous one (rm) succeds. So this can be used to log a successful removal.
You will receive an error message from rm if a removal fails (eg. permission denied).
rm -f suppresses "does not exist" errors, and you wouldn't get a success message either, however find won't pass a non-existent directory.
Related
I am trying to execute a shell script which has the following within it:
find /hana/shared/directory -type d -mtime +2 -exec rm -rf {} \;
This works on other SUSE Linux servers but on one. It keeps returning the following:
find: missing argument to -exec
If, however, I place the same syntax into a terminal and run it manually, it runs without issue.
I can see this is a common issue, but I believe I have tried many of the suggestions to no avail and I'm a bit stuck now.
Very carefully read find(1), proc(5), and the GNU Bash documentation.
You might want to run (this is dangerous; see below):
find / -type d mtime +2 -exec /bin/rm -f '{}' \;
(use at least -ok instead of -exec)
And you probably want to clean just your $HOME.
But you should avoid removing files from /proc/, /sys/, /dev/, /lib/, /usr/, /bin/, and /sbin/. See hier(7) and environ(7).
I want to find a folder in a known folder but with unknown exact path, thus I must use find. When I find it, I use -exec to remove it, but I cannot evaluate if this has succeeded. Behavior somewhat confuses me; if I don't find the folder, I get return code 0:
>find . -name "testuuu" -exec rm -r {} \;
find: ‘./.docker’: Permission denied
>echo $?
0
But when I do find the folder and manage to delete it, it returns error code 1:
> find . -name "test" -exec rm -r {} \;
find: ‘./.docker’: Permission denied
find: ‘./test’: No such file or directory
> echo $?
1
Is this expected behavior? Why?
Further, how can I get return code of "rm" and not "find" and thus evaluate if the folder was deleted?
Use the -depth option to order a depth-first traversal -- that way find doesn't try to find things under your directory after the directory has already been deleted (an operation which, by nature, will always fail).
find . -depth -name "test" -exec rm -r -- '{}' \;
This option is also turned on by default when you use the -delete action in GNU find to delete content.
By the way -- if there are lots of test directories, you could get better performance by making that -exec rm -r -- {} + (which passes each copy of rm as many filenames as will fit on its command line) instead of -exec rm -r -- {} \; (which starts a new copy of rm for each test that is found), at the expense of no longer collecting individual error codes.
How can I delete all subdirectories of a certain name via the command line on mac?
Eg if I have
/parent/foo
/parent/child/foo
/parent/child/child2/foo
How can I run a command from /parent that will delete any folder called foo and all of it's contense?
Ive tried this command but no luck:
find . -type d -name foo -delete
Using find you can do:
find . -d -type d -name a -exec rm -r {} \;
As you have discovered -delete does not appear to delete non-empty directories (so its equivalent to rmdir not rm -r), though this may not be documented.
The -exec executes a command, {} is replaced by the matching pathname, and \; marks the end of the command. So this does a recursive removal of every matching path.
The -d sets depth first traversal which means directories are processed after their contents. If you omit this find will first remove the directory and then try to recurse into it – this results in error messages but still works.
There is a shorter way using zsh:
rm -r **/a
The pattern ** does a search an matches a at any depth.
If zsh is not your default shell you can use its -c argument to run a command from another shell:
zsh -c 'rm -r **/a'
HTH
The name of the directory has to be in quotes.
Do the following:
find . -type d -name "foo" -delete
I have set up a bamboo job to delete files and folders on a server at a particular location for files/folders older than 15 days and the job runs fine and deletes the files/folders but then the shell command exits with code 1 due to "Permissions denied" and "No such files or directory" errors which are always expected and hence the whole build fails. We want it to report success.
Is there a way to skip these errors and delete files modified older than 15 days for those files only where the shell command can return always 0.
find ./* -type d -ctime +15 -exec rm -rf {} \;
Since the exit code of a script is that of its last command, you can add any "true" command in the end. There's true, as well as : though tricky:
find ./* -type d -ctime +15 -exec rm -rf {} \;
: always true here
For the explanation of :, See Bourne Shell Builtins.
You could try something like:
find ./* -type d -ctime +15 -exec rm -rf {} \; || true
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.