Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I want to delete all files in the current directory and sub directories whose file name is more than a particular length.

Is there an easy way of doing this from bash?

share|improve this question
    
Asking questions to yourself, Kitsos? –  MariusMatutiae Jan 15 at 13:29
    
@MariusMatutiae yes, and this is both OK and encouraged on the SE sites. I am also interested in other ways of doing this though. –  Kitsos Jan 15 at 14:44

2 Answers 2

up vote 2 down vote accepted

You have already provided a find command that is safe for oddly named files:

find -regextype posix-egrep -type f -regex '.*[^/]{5}' -delete

This regex matches five trailing characters that do not contain a slash (i.e. the filename is longer than five chars).

The Bash loop you provided will generally work, but it probably does not scale with thousands of files and may break with special filenames.

An alternative that is similar in efficiency, but may provide more flexibility (replace rm by -n1 echo to print all files):

find -type f -print0 | grep -Ez '[^/]{5}$' | xargs -0 rm

The -print0, -z and -0 options ensure that each file name is terminated with a NUL byte. This ensures that special characters do not split filenames (newlines break the Bash command you provided). Although this grep command still fails with a name such as path/abc\ndef (where \n is a newline), it won't be split up into path/abc and def.

As you will rarely find files with \n in their name, I leave the implementation for that case as an exercise to the reader.

share|improve this answer
    
Thanks, I accepted this so I don't accept mine but the find -delete actually is the safest way of dealing with weird names (including newlines). The bash loop in my answer will only break if the names contain `, it can deal with everything else AFAIK, including spaces and new lines. Granted that xargs` with the correct arguments for parallelization will probably be faster but I tend to go for the safe one when I don't know what files I'm dealing with. –  Kitsos Jan 26 at 21:13
    
@Kitsos I did not say faster, but flexible. If you need to post-process the file list, then external programs may be easier than using a find regex. Your bash answer will fail with newlines. Consider a file name names foo\nbar (with an embedded newline). Then the first iteration will read foo and the second one bar. If you had files named foo or bar, then you will lose them, even if the length of foo\nbar is longer than five (seven). Another useful property find is that the -delete options removes empty directories too. –  Lekensteyn Jan 26 at 22:21

You can use find to locate all files in the current directory and subdirectories, then measure the length of the file name using bash and delete accordingly:

$ find . -type f | while IFS= read -r file; do 
    ## find will return the full path, strip the
    ## path from the file name. 
    name=$(basename "$file"); 
    ## Check the name'slength and delete if > 5
    [ "${#name}" -gt 5 ] && rm "$file"; 
  done

Alternatively, you can do everything from find by using -regex and -delete. For example, to delete file name of more than 5 characters (excluding the path):

find . -type f -regextype posix-egrep -regex '.*[^/]{5}' -delete
share|improve this answer
    
{5,} to be precise. It's <i>more than a particular length</i>. Not to be pedantic but to avoid misunderstandings on the use of quantifiers. –  Peter Jan 15 at 14:25
    
@Peter as far as I know, the {N,X} format is exclusive to PCREs which find does not support. In the posix-egrep format, {5} means "five or more", try it. –  Kitsos Jan 15 at 14:45
    
For the rm command, change $name to $file for this to work properly. Was just thinking about implementing in Perl, and it is such a straight conversion. –  Bill McCloskey Jan 15 at 15:22
    
@Kitsos that's why I mentioned it. The regular expression without the additional ',' in the quantifier didn't work for me, though I thought the approach is quiet elegant, so I modified it. –  Peter Jan 15 at 15:41
    
LSB Version: core-2.0-noarch:core-3.2-noarch:core-4.0-noarch:core-2.0-x86_64:core-3.2-x86_64:‌​core-4.0-x86_64:desktop-4.0-amd64:desktop-4.0-noarch:graphics-2.0-amd64:graphics-‌​2.0-noarch:graphics-3.2-amd64:graphics-3.2-noarch:graphics-4.0-amd64:graphics-4.0‌​-noarch Distributor ID: openSUSE project Description: openSUSE 12.3 (x86_64) Release: 12.3 Codename: Dartmouth –  Peter Jan 15 at 15:43

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.