linux - without - shell script to delete files in a directory




Remove all files in a directory(do not touch any folders or anything within them) (6)

I would like to know whether rm can remove all files within a directory (but not the subfolders or files within the subfolders)?

That's easy:

$ rm folder/*

Without the -r, the rm command won't touch sub-directories or the files they contain. This will only remove the files in folder and not the sub-directories or their files.

You will see errors telling you that folder/foo is a directory can cannot be removed, but that's actually okay with you. If you want to eliminate these messages, just redirect STDERR:

$ rm folder/* 2> /dev/null

By the way, the exit status of the rm command may not be zero, so you can't check rm for errors. If that's important, you'll have to loop:

$ for file in *
> do
> [[ -f $file ]] && rm $file
> [[ $? -ne 0 ]] && echo "Error in removing file '$file'"
> done

This should work in BASH even if the file names have spaces in them.

I would like to know whether rm can remove all files within a directory (but not the subfolders or files within the subfolders)?

I know some people use:

rm -f /direcname/*.*

but this assumes the filename has an extension which not all do (I want all files - with or without an extension to be removed).


A shell solution (without the non-standard find -maxdepth) would be

for file in .* *; do
   test -f "$file" && rm "$file"
done

Simple shell globbing will do:

% tree
.
├── 1
├── 2
├── 3
├── 4
├── 5
└── bar
    ├── a
    ├── b
    ├── c
    ├── d
    └── e

1 directory, 10 files

% rm -f *
rm: cannot remove ‘./bar’: Is a directory

% tree .
.
└── bar
    ├── a
    ├── b
    ├── c
    ├── d
    └── e

1 directory, 5 files

as in Jens' answer, you might need to add a second rm -f .* but this is only if you expect hidden files in your main directory. No need to check for type (test -f) as the rm -f option will not remove directories. This however will also delete "special" files such as symbolic links and block devices.


Some shells, notably zsh and perhaps bash version 4 (but not version 3), have a syntax to do that.

With zsh you might just type

rm /dir/path/*(.)

and if you would want to remove any file whose name starts with foo, recursively in subdirectories, you could do

rm /dir/path/**/foo*(.)

the double star feature is (with IMHO better interactive completion) in my opinion enough to switch to zsh for interactive shells. YMMV

The dot in parenthesis suffix indicates that you want only files (not symlinks or directories) to be expanded by the zsh shell.


Unix isn't DOS. There is no special "extension" field in a file name. Any characters after a dot are just part of the name and are called the suffix. There can be more than one suffix, for example.tar.gz. The shell glob character * matches across the . character; it is oblivious to suffixes. So the MS-DOS *.* is just * In Unix.

Almost. * does not match files which start with a .. Objects named with a leading dot are, by convention, "hidden". They do not show up in ls either unless you specify -a.

(This means that the . and .. directory entries for "self" and "parent" are considered hidden.)

To match hidden entries also, use .*

The rm command does not remove directories (when not operated recursively with -r). Try rm <directory> and see. Even if the directory is empty, it will refuse.

So, the way you remove all (non-hidden) files, pipes, devices, sockets and symbolic links from a directory (but leave the subdirectories alone) is in fact:

rm /path/to/directory/*

to also remove the hidden ones which start with .:

rm /path/to/directory/{*,.*}

This syntax is brace expansion. Brace expansion is not pattern matching; it is just a short-hand for generating multiple arguments, in this case:

rm /path/to/directory/* /path/to/directory/.*

this expansion takes place first first and then globbing takes place to generate the names to be deleted.

Note that various solutions posted here have various issues:

find /path/to/directory -type f -delete

# -delete is not Unix standard; GNU find extension
# without -maxdepth 1 this will recurse over all files
# -maxdepth is also a GNU extension
# -type f finds only files; so this neglects to delete symlinks, fifos, etc.

The GNU find solutions have the benefit that they work even if the number of directory entries to be deleted is huge: too large to pass in a single call to rm. Another benefit is that the built-in -delete does not have issues with passing funny path names to an external command.

The portable workaround for the problem of too many directory entries is to list the entries with ls and pipe to xargs:

( cd /path/to/directory ; ls -a | xargs rm -- )

The parentheses mean "do these commands in a sub-process"; this way the effect of the cd is forgotten, which is useful in scripting. ls -a includes the hidden files.

We now include a -- after rm which means "this is the last option; everything else is a non-option argument". This guards us against directory entries whose names are indistinguishable from options. What if a file is called -rf and ends up the first argument? Then you have rm -rf ... which will blow off subdirectories.


You can use

find /direcname -maxdepth 1 -type f -exec rm -f {} \;




unix