- How to remove files and directories quickly via terminal (bash shell) [closed]
- 4 Answers 4
- How to delete all directories with a particular name?
- 1 Answer 1
- How do I remove a directory and all its contents?
- Delete files and folders with specific name from a certain directory
- 3 Answers 3
- Delete all folders inside a folder except one with specific name
- 6 Answers 6
- How it works
- Example
- tl;dr
How to remove files and directories quickly via terminal (bash shell) [closed]
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
From a terminal window: When I use the rm command it can only remove files.
When I use the rmdir command it only removes empty folders. If I have a directory nested with files and folders within folders with files and so on, is there a way to delete all the files and folders without all the strenuous command typing? If it makes a difference, I am using the Mac Bash shell from a terminal, not Microsoft DOS or Linux.
Just in case you wish to restore the files in future , don’t use «rm» for such cases . Use «rm-trash» : github.com/nateshmbhat/rm-trash
4 Answers 4
-r «recursive» -f «force» (suppress confirmation messages)
+1 and glad you added the «Be careful!» part. definitely a «Sawzall» command that can quickly turn a good day into a bad one.. if wielded carelessly.
@itsmatt: You know what they say. give someone a Sawzall, and suddenly every problem looks like hours of fun!
On a Mac? Do this instead: brew install trash then trash -rf some_dir This will move the unwanted directory into your trashbin instead of just vanishing Prestige-style into the ether. (source)
Would remove everything (folders & files) in the current directory.
But be careful! Only execute this command if you are absolutely sure, that you are in the right directory.
Yes, there is. The -r option tells rm to be recursive, and remove the entire file hierarchy rooted at its arguments; in other words, if given a directory, it will remove all of its contents and then perform what is effectively an rmdir .
The other two options you should know are -i and -f . -i stands for interactive; it makes rm prompt you before deleting each and every file. -f stands for force; it goes ahead and deletes everything without asking. -i is safer, but -f is faster; only use it if you’re absolutely sure you’re deleting the right thing. You can specify these with -r or not; it’s an independent setting.
And as usual, you can combine switches: rm -r -i is just rm -ri , and rm -r -f is rm -rf .
Also note that what you’re learning applies to bash on every Unix OS: OS X, Linux, FreeBSD, etc. In fact, rm ‘s syntax is the same in pretty much every shell on every Unix OS. OS X, under the hood, is really a BSD Unix system.
How to delete all directories with a particular name?
Under a directory, I have a bunch of directories named Debug . How do I delete all the Debug directories?
1 Answer 1
It’s not clear — under the directory dir_a you can have only one directory named Debug . Or are you saying that you have dir_a/Debug , dir_a/dir_b/Debug , dir_a/dir_c/Debug and so on?
You can list all directory named exactly Debug under the directory dir_a with:
cd dir_a # or whatever you need to go there find . -type d -name Debug
this will list all the directories named Debug under the current directory. To delete them (double check, this IS NOT UNDOABLE):
find . -depth -type d -name Debug -exec rm -r <> \;
-depth will list Debug/Debug/ before Debug/ to avoid errors.
- find . -type d -name Debug will search all directory under the current one ( . ) for entries which are both directory ( -type d ) and have the name «Debug» ( -name Debug ).
- The added -depth flag make the search depth-first (it means that «deeper» matches are found before «shallow» ones).
- -exec . \; tells find to execute the command in . for each match. (The semicolon is quoted because otherwise the shell will interpret it).
- In the command . above, the special symbol <> is substituted by the current match.
So in plain English it is: find every directory under this one which name is «Debug», depth first, and for each one execute the command rm -r followed by the full name of the directory.
How do I remove a directory and all its contents?
The following command will do it for you. Use caution though if this isn’t your intention as this also removes files in the directory and subdirectories.
«-f» is «—force» which overrides some sanity checks and prompting. A safer command to start with would be rm -r directoryname .
@JimParis I think the word «safer» is relative. Suppose you are writing a script to run on a remote computer. That script has a command which is supposed to remove a directory. Here, it would be «safer» to use rm -rf directoryname coz you wouldn’t want your script to pause execution, because it’s waiting for user input. Of course, you have to be sure that deleting the directory would do no harm.
if rm -rf directoryname fails you, try using rm -R -f directoryname , or rm —recursive -f directoryname .
If you are not having any luck with these, you should consider reinstalling rm or switching shells.
These were the options available on my rm man page, I looked it up by typing man rm to view my options on recursive deletion and the force options.
Does your rm man page list -r ? What does it do? (Try it in a directory that you create just for testing purposes, with only dummy files (and maybe subdirectories) in it.) What operating system are you using?
P.S. If rm -r doesn’t work, that would be an OS issue, not a shell issue. (Strictly speaking, it would be an issue with the version of rm that you’re using, so you could address it by installing a different version of rm , or searching your system to see whether you already have a different version of rm in some directory other than /bin .)
Ah, right. I forgot to mention I’m on Ubuntu 14.04 When I ran man rm in my terminal, it gave me a text file with the less text viewer. I scrolled found an indented entry with a whole that had the -R and —recursive options cozied up with the -r option, signifying that all of those arguments are identical.
edit: have you tried sudo rm -r directoryName ? The unwritten rules of the basic commands is that -r will allow a program to run recursively on every file your filesystem (starting where ever you choose!) and that -f will forcefully do things, even if it’s dangerous. ‘cd’, ‘mv’, ‘ls’ mostly holds this principle true. ls -r / is gonna be a duzie, and cp -rf / /dev/null will destroy everything on your filesystem.
Other answers show how to completely remove a directory’s content, but IMO they don’t address the literal question of the original post — that is, how can one delete subdirectories (as opposed to usual files). In other words, how can one delete empty directory structures while keeping subdirectories containing files ?
This can be achieved with find :
find directoryname -type d -delete
This command will recursively search for directories ( -type d ) through directoryname and -delete them only if their subdirectories or themselves don’t contain any files.
Delete files and folders with specific name from a certain directory
I have a folder /home/userA/folderA this folder contains many files and folders and subfolders. What I want to do is to delete all files that have certain names data.txt and glass.txt . I also want to delete any folder named match with all its contents. I’d be thankful for any advice in how to do this.
3 Answers 3
You can delete the files and folders in the subdirectories of folderA .
find /home/userA/folderA/* -type f \( -name "data.txt" -or -name "glass.txt" \) -delete
and to remove the folders match :
find /home/userA/folderA/* -depth -name "match" -type d -exec rm -rf "<>" \;
its giving this error find: invalid expression; I was expecting to find a ‘)’ somewhere but did not see one.
Try: find /home/userA/folderA/* -depth -name «data.txt» -type f -exec rm <> \; and find /home/userA/folderA/* -depth -name «glass.txt» -type f -exec rm <> \;
And the verbose (python) option:
#!/usr/bin/env python3 import os import shutil # -------------------------------------------------------- reorg_dir = "/path/to/your/folder" remove_files = ("data.txt", "glass.txt") remove_dirs = ("match") # --------------------------------------------------------- for root, dirs, files in os.walk(reorg_dir): for name in files: if name in remove_files: os.remove(root+"/"+name) for dr in dirs: if dr in remove_dirs: shutil.rmtree(root+"/"+dr)
Copy the script into an empty file, set the directory and if you want/need: edit the list of files and folders to remove, save it as reorg.py and run it by the command:
Delete all folders inside a folder except one with specific name
I need to delete all folders inside a folder using a daily script. The folder for that day needs to be left. Folder ‘myfolder’ has 3 sub folder: ‘test1’, ‘test2’ and ‘test3’ I need to delete all except ‘test2’. I am trying to match exact name here:
find /home/myfolder -type d ! -name 'test2' | xargs rm -rf
find /home/myfolder -type d ! -name 'test2' -delete
6 Answers 6
This will delete all folders inside ./myfolder except that ./myfolder/test2 and all its contents will be preserved:
find ./myfolder -mindepth 1 ! -regex '^./myfolder/test2\(/.*\)?' -delete
How it works
- find starts a find command.
- ./myfolder tells find to start with the directory ./myfolder and its contents.
- -mindepth 1 not to match ./myfolder itself, just the files and directories under it.
- ! -regex ‘^./myfolder/test2\(/.*\)?’ tells find to exclude ( ! ) any file or directory matching the regular expression ^./myfolder/test2\(/.*\)? . ^ matches the start of the path name. The expression (/.*\)? matches either (a) a slash followed by anything or (b) nothing at all.
- -delete tells find to delete the matching (that is, non-excluded) files.
Example
Consider a directory structure that looks like;
$ find ./myfolder ./myfolder ./myfolder/test1 ./myfolder/test1/dir1 ./myfolder/test1/dir1/test2 ./myfolder/test1/dir1/test2/file4 ./myfolder/test1/file1 ./myfolder/test3 ./myfolder/test3/file3 ./myfolder/test2 ./myfolder/test2/file2 ./myfolder/test2/dir2
We can run the find command (without -delete ) to see what it matches:
$ find ./myfolder -mindepth 1 ! -regex '^./myfolder/test2\(/.*\)?' ./myfolder/test1 ./myfolder/test1/dir1 ./myfolder/test1/dir1/test2 ./myfolder/test1/dir1/test2/file4 ./myfolder/test1/file1 ./myfolder/test3 ./myfolder/test3/file3
We can verify that this worked by looking at the files which remain:
$ find ./myfolder ./myfolder ./myfolder/test2 ./myfolder/test2/file2 ./myfolder/test2/dir2
Excellent work!, but sorry: that will remove all files inside ./myfolder . You need a missing (IMvhO) -type d for only directories.
Ok, this should work as you want: find ./myfolder -depth -mindepth 1 -maxdepth 1 -type d ! -regex ‘^./myfolder/test2\(/.*\)?’
shopt -s extglob rm -r myfolder/!(test2)/
$ tree myfolder/ myfolder/ ├── test1 │ └── file1 ├── test2 │ └── file2 └── test3 └── file3 $ echo rm -r myfolder/!(test2) rm -r myfolder/test1 myfolder/test3 $ rm -r myfolder/!(test2) $ tree myfolder/ myfolder/ └── test2 └── file2 1 directory, 1 file
tl;dr
find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 \ -exec echo rm -rf '<>' \;
Remove echo if satisfied with the list of files.
Using -mindepth 1 will ensure that the top directory is not selected.
$ find ./myfolder -mindepth 1 -type d ./myfolder/test2 ./myfolder/test2/one ./myfolder/test2/two ./myfolder/test ./myfolder/test/a1 ./myfolder/test/a1/a2 ./myfolder/test/a1/a2/a3
But a -not -name test2 will not avoid subdirs inside test2 :
$ find ./myfolder -mindepth 1 -type d -not -name 'test2' ./myfolder/test2/one ./myfolder/test2/two ./myfolder/test ./myfolder/test/a1 ./myfolder/test/a1/a2 ./myfolder/test/a1/a2/a3
To do that, you need something like prune:
$ find ./myfolder -mindepth 1 -name test2 -prune -o -type d -print ./myfolder/test ./myfolder/test/a1 ./myfolder/test/a1/a2 ./myfolder/test/a1/a2/a3
But do not use delete , as it implies depth and that will start erasing from the longest path:
$ find ./myfolder -depth -mindepth 1 -name test2 -prune -o -type d -print ./myfolder/test/a1/a2/a3 ./myfolder/test/a1/a2 ./myfolder/test/a1 ./myfolder/test
Either use rm -rf (remove the echo if you want to actually erase):
$ find ./myfolder -mindepth 1 -name test2 -prune -o -type d -exec echo rm -rf '<>' \; rm -rf ./myfolder/test rm -rf ./myfolder/test/a1 rm -rf ./myfolder/test/a1/a2 rm -rf ./myfolder/test/a1/a2/a3
Or, also use maxdepth if all you need is to delete directories (and everything inside) (remove the echo to actually erase):
$ find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 -exec echo rm -rf '<>' \; rm -rf ./myfolder/test
A -delete will still fail if the directory is not empty:
$ find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 -delete find: cannot delete ‘./myfolder/test’: Directory not empty