Finding all files that have whitespace in last few lines

Viewed 64

I am attempting to search all the files in a website for any whitespace that is in the last 5 lines of each files and want the terminal to return a list of any files that meet that criteria.

The reason for this is that we have problems on a Drupal site where whitespace is being injected into images which causes them to become corrupt and won't show.

I've tried a few things below, none of which give me the desired results although I believe that I am quite close to getting the right command.

I've scoured the internet and stackexchange and found some answers that I believed would work but sadly not for me.

Attempt #1

find . -name "*.php" | xargs grep -c -P '\s+$' | grep -v ':0$'

At first, this appeared to work in listing all files with a whitespace but I found it wasn't specific enough and gave a list of around 500 files, not all of which ended in a whitespace. I started to plod through them but then realised it was not giving me a list of all the files that had whitespaces in so found another method.

Attempt #2

find . -type f -exec bash -c 'grep -q  " +$" < <(tail -n 5 "$1")' _ {} \; -printf '%p\n'

All this listed was two JS files which wasn't very helpful.

Attempt #3

find . -type f -exec bash -c 'grep -q " +$" < <(tail -n 5 "$1") && printf '%\n' "$1"' _ {} \;

Again, this returned the same two JS files.

2 Answers

You where almost there

grep -q  " +$"

won't work because the modifier + is part of the extended regular expressions, and grep works by default with the basic/POSIX regular expressions (where the +-sign is interpreted as a literal character).

There are two solutions:

  1. Switch to extended regex using the flag -E: grep -qE " +$" or by adding the backslash before the + sign: grep -q " \+$"
  2. But because (in my experience) extended regexes are slower in Unix than the basic ones, and you want to find files with 'one or more spaces at the end': grepping on 'one space at the end' will also list the appropiate files: thus grep -q " $"

You have to escape the + inside grep expression, ex. see gnu grpe manual.

Using < <(...) shell redirection with process substitution is unneeded here, just pipe it |.

The following works. Notice how I needed to double escape \\+, because \\ is expanded to \ inside " braces.:

find . -type f -exec sh -c 'tail -n 5 "$1" | grep -q " \\+$" && printf "%s\n" "$1"' -- {} \;

However when using xargs you can do it in parallel -P0, also I like the debugging with -t better. For strange filenames add -print0 and -0 options to find and xargs.

find . -type f | xargs -n1 sh -c 'tail -n 5 "$1" | grep -q " \\+$" && printf "%s\n" "$1"' --
Related