There isn't any direct security risk with making a file executable unless it's setuid or setgid. Of course, there's the indirect risk that something you expect to be inert — some data file that you'd normally open in an application — can also be executed directly on your system with nefarious consequences. For example, if you have a file called README that actually contains a rootkit program, opening it in a text editor is safe, but you'd better not execute it.
A reasonable heuristic to recognize files that are meant to be executable is to look at their first few bytes and recognize executable signatures. This is a matter of convenience rather than security, but if you're willing to make all files executable anyway, it means you don't have a security concern but a usability concern anyway. Here's a possible heuristic:
for x in *; do
case $(file - <"$x") in
*executable*) chmod +x -- "$x";;
esac
done
Here's another heuristic which should differ only in corner cases ($'\177'
is ksh/bash/zsh syntax, replace it by a literal character 0177 = 127 = 0x7f in other shells).
for x in *; do
case $(head -c 4 <"$x") in
'#!'*|$'\177'ELF) chmod +x -- "$x";;
esac
done
In both cases, just because a file is recognized as executable doesn't mean you can execute it on your system; for example a binary for the wrong processor architecture will be happily made executable. Here's a different approach that makes all scripts executable, but dynamically linked binaries only if they're for the right architecture and you have the required libraries, and misses statically linked binaries altogether.
for x in *; do
case $(head -c 2 <"$x") in
'#!') chmod +x -- "$x";;
*) if ldd -- "$x" >/dev/null 2>/dev/null; then chmod +x "$x"; fi;;
esac
done
tar
file instead? – Mat Nov 11 '11 at 11:13