find command delete option failed to remove folders - bash

I'm trying to all subdirectories and its contents with the name "bin". I've used the find command with option -delete to perform the delete and it has worked to some degree (JFX folders begin at 01 and I've managed to delete "bin" folders up to JFX13). However, not all "bin" folders and its contents are deleted, which makes me very puzzled.
I would appreciate if anyone can figure out what I'm not doing correctly.
Here's how it looks right now

According to the man page of find, -delete is for deleting files also folders but only if there are no files inside. So instead of first deleting the files and then the folders again, I would suggest to use -exec with rm -rf to clean up altogether in one-shot.
find . -name "bin" -type d -exec rm -rf "{}" +
The actual information from te man find page,
-delete
Delete files; true if removal succeeded. If the removal
failed, an error message is issued. If -delete fails, find's
exit status will be nonzero (when it eventually exits). Use
of -delete automatically turns on the `-depth' option.
This calls rm -rf on the all the folders returned from find command in one-shot rather than involing one rm command for every folder found.
Note:- Use rm -rf carefully. Run this only if you are absolutely sure of the folders you want to delete, avoid running it otherwise.

Related

removing directory and sub directory which is not present in the list

This is my directory structure
find -type f -print0 | xargs -0 ls -t
./lisst.txt ./SAMN03272855/SRR1734376/SRR1734376_1.fastq.gz
./SAMN03272854/SRR1734375/SRR1734375_2.fastq.gz ./SAMN07605670/SRR6006890/SRR6006890_2.fastq.gz
./SAMN03272854/SRR1734375/SRR1734375_1.fastq.gz ./SAMN07605670/SRR6006890/SRR6006890_1.fastq.gz
./SAMN03272855/SRR1734376/SRR1734376_2.fastq.gz
So this is a small subset of my folder/files where i have around 70.
I have a made a list of files which i want to keep and other i would like to delete.
My list.txt contains SAMN03272854,SAMN03272855 but I want to remove SAMN07605670.
I ran this
find . ! -name 'lisst.txt' -type d -exec rm -vrf {} +
It removed everything
QUESTION UPDATE
In my list it contains the folder i want to keep and the one which are not there are to be removed.
The folders which are to be removed also contains subdirectories and files. I want to remove everything
Your command selects each directory in the tree, except a directories of the funny name lisst.txt. Once it finds a directory, you do a recursive remove of this directory. No surprise that your files are gone.
You can't use rm -r when you want to spare certain files from deletion. This means that you also can't remove a directory, which somewhere below in its subtree has a file you want to keep.
I would run two find commands: The first removes all the files, ignoring directories, and second one removes all directories, which are empty (bottom-up). Assuming that SAMN03272854 is indeed a file (as you told us in your question), this would be:
find . -type f \( ! \( -name SAMN03272854 -o -name SAMN03272855 \) \) -exec rm {}
find . -depth -type d -exec rmdir {} 2>/dev/null
The error redirection in the latter command suppresses messages from rmdir for directories which still contain files you want to keep. Of course other messages are also suppressed. I would during debugging run the command without error redirection, to see whether it is basically correct.
Things would get more complicated, if you have files and directories to keep, because to keep a directory likely implies to keep all the files below it. In this case, you can use the -prune option of find, which excludes directories including their subdirectories from being processed. See the find man page, which gives examples for this.

Iteratively deleting files of a specific type

I have subfolders with .tmp files that I wish to delete, and trying to find a one-liner for doing so.
for item in folder1/*/*; do rm *.tmp; done
From this I get a bunch of messages saying:
rm: cannot remove ‘*.tmp’: No such file or directory
I get the same problem when I try doing other operations. What am I missing here?
P.S. I know I could recursively delete without a for loop with rm -rf *.tmp but I would like to know how to do it using an iterative loop, so that I can use it to perform other actions apart from rm by just replacing the "action" part of the statement.
Thanks in advance,
Jan
You can use:
find folder1 -mindepth 2 -maxdepth 2 -type f -name "*.tmp" -exec rm -f {} \;
This is going to find files (-type f) in the second directory level only (-mindept 2 -maxdepth 2) which name end with "tmp", and delete them.
You can try with "ls" instead of "rm" first, to check if the command is finding what you are looking for.

Remove files in directory and ignore if empty-BASH

By using the command :
rm /file_path/*.csv
I can delete all csv files in the required folder.However if the directory is empty or there are no csv files I get the following error:
No such file or directory
How do I avoid this error?I have this logic in a script with certain downstream dependancies so throwing this error will cause the rest of my code to stop.Whats the best way in bash to delete files only if they exist in the directory?
Another variant is to check if your folder is empty before to run your script:
find file_path/ -type d -empty
It returns the name of your folder if it is empty.
Or use the "-f" option with rm command if you want only avoid the error message:
Without:
rm -r file_path/*.csv
rm: cannot remove ‘file_path/*.csv’: No such file or directory
With:
rm -rf file_path/*.csv
See Test whether a glob has any matches in bash for ways to check if /file_path/*.csv matches anything. However, even if you do such a test before running the rm command it may fail if the directory has a very large number of CSV files. See Argument list too long error for rm, cp, mv commands.
If you have a modern version of find, this is a reliable and efficient option:
find /file_path -maxdepth 1 -type f -name '*.csv' -delete
You can do: [ -f /file_path/*.csv ] && rm /file_path/*.csv

How to delete all files or Sub-folders (both) in a folder except 2 folders with shell script

I would like to know how to deleted all the contents of a folder (it contains other folders and some files) except for 2 folders and its contents
The below command keeps the folder conf and removes all the other folders
find . ! -name 'conf' -type d -exec rm -rf {} +
I have tried to pipe it like below
find . -maxdepth 1 -type d ! -name 'conf' |find . -maxdepth 1 -type d ! -name 'foldername2'
but didnt work.
is it possible to do with a single command
You haven't specified which shell you're using, but if you're using bash then extended globs can help:
printf '%s\n' !(#(conf|foldername2)/)
If you're happy with the list of files and directories produced by that, then pass the same glob to rm -rf:
rm -rf !(#(conf|foldername2)/)
Inside a script, you may need to enable extglob using shopt -s extglob. Later, you can change -s to -u to unset the option.
If you're using a different shell, then you can add some more options to your find command:
find -maxdepth 1 ! -name 'conf' -a ! -name 'foldername2' -exec rm -rf {} +
Try it without the -exec part first to print the matches rather than deleting everything.
It may my little program utility can help you. I hope so.
First of all you should find the path of your files .sh
then you should find the main folder that contains those files .sh
then remove anything except those folders
I wrote drr for such a purpose that it can do such a task so easy
drr, stands for: remove or rename files based on regular expression in D language. So you must compile it before using.
See the screenshot:
Please be careful since this is not an appropriate tool for beginner.

How to delete files of certain name from terminal recursively

I would like to delete all the emacs backup (~) files from subfolders.
I am aware that I can cd in every single folder and delete them using rm *~ (e.g. for backup file test.cpp~).
How I can delete these files with one command, without cd'ing in every folder?
(I tried rm -r *~ and rm -rf *~ but they don't seem to work)
You can do this with find and exec. Here's an example that does what you want to do:
find -name '*~' -exec rm {} \;
Let's break it down how this works. The find command will recurse through the directory it's executed from, and by default it will print out everything it finds. Using -name '*~' tells us only to select entries whose name matches the regex *~. We have to quote it because otherwise the shell might expand it for us. Using -exec rm {} will execute rm for each thing it finds, with {} as a placeholder for the filename. (The final ; is something required to tell find that this is where the command ends. It's not really a big deal but it'll whine and do nothing if you don't use it. The \ is to escape it because ; is a special shell character.)
find /path/to/directory/ -type f -name '*filtercondition*' -delete
Above command will find the file recursively in the folder matching pattern and delete Files only
You would use find:
find ./ -name *~ -exec rm {} \;
This command will recursively list all files, that match the pattern given for the name. Then it'll execute the command provided for each one of them, substituting the curly braces with the filename.
The only tricky part is the semicolon, as that is closing the command, but it must be protected from bash, hence the backslash.
See https://linux.die.net/man/1/find for more options.
First, the best way to delete these files is to not create them (or rather, create them in a central place): https://stackoverflow.com/a/151946/245173
Here's a way to use find from Emacs to gather a list of files and selectively do operations on them. M-x find-name-dired RET /path/to/files RET *~ RET should get all of the backup files under /path/to/files/ and put them in a dired buffer. Then you can do normal dired things like mark files with m, invert the selection with t, and delete the selection with D.

Resources