Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a folder containing many C source file and the same number of its compiled output files.

I set executable bit to all this files but for some reason it was lost, making them not executable. (I think that's because I moved that folder to a NTFS partition for a while).

I would like to make them (but not the other files in my directory) executable again. One possible way is to move all source file from that folder to a temporary folder and do:

chmod +x *

Then move source files back to current folder.

Is it possible to do the same without moving files around?

Note:

Compiled output files are extension-less (in C).

share|improve this question
    
So you want to add executable bit to all files in current directory that do not have any extension in their name, right (so no dot in filename)? –  Krzysztof Adamski Oct 4 '12 at 12:20
    
@KrzysztofAdamski Yes –  Santosh Kumar Oct 4 '12 at 15:39
add comment

4 Answers

up vote 8 down vote accepted

That depends on how you define which files should be set as executables. For example, if consider all the files that do not have dot in filename, you can use:

find -type f -not -name "*.*" -exec chmod +x \{\} \;

This will find recursively all the files (not directories) that do not have dot in file name and set them executable. If you want to limit this to only current directory, add -maxdepth 1 argument, like this:

find -maxdepth 1 -type f -not -name "*.*" -exec chmod +x \{\} \;

You could also rely on file command which could tell you if a file is ELF executable. To do this, you could run something like:

find -type f -exec /bin/sh -c "file {} | grep -q executable && chmod +x {}" \;

This will recursively find all regular files and call file command on them. Then, grep will look for "executable" string in the output of this command (it should be something like ELF 32-bit LSB executable ...) and only if it finds it, chmod will be called on this file.

Of course, you can also add -maxdepth 1 in this case to disable recursive searching.

share|improve this answer
add comment

You could do something like:

find /pathtostuff -type f ! -name "*.c" -exec chmod +x {} +

This looks in /pathtostuff for files that lack a .c extension and adds the execute permissions to them.

UPDATE

This can be expanded to handle other C extensions too:

find . -type f ! -name "*.c" ! -name "*.h" ! -name "*.cc" ! -name "*.cpp" -exec chmod +x {} +

ALTERNATIVE APPROACH

This script is extension agnostic. It looks for files that are "binary" as opposed to "text".

#!/usr/bin/env perl
use strict;
use warnings;
use File::Find;
my @dir = @ARGV ? @ARGV : ('.');
my @files;
find( sub { -f $_ && !-T $_ && push @files, $File::Find::name }, @dir );
for my $file (@files) {
    system("echo  +x $file");
}

Simply pass the directory path to be examined. Run the script without any argument to process the current working directory.

share|improve this answer
    
I'm surprised! It didn't asked for password. –  Santosh Kumar Oct 4 '12 at 15:42
    
What if I want to exclude another extension? Say .cc. –  Santosh Kumar Oct 4 '12 at 15:42
1  
This is not really ideal since there may be .o/.h/.cpp and other files. –  Krzysztof Adamski Oct 4 '12 at 15:45
1  
@SantoshKumar: it don't need password for anything. Password is only needed when you use sudo command which is used to gain root privileges. As long as you run chmod on the files owned by the user you are logged in as, you don't have to use sudo. –  Krzysztof Adamski Oct 4 '12 at 16:10
1  
@JRFerguson: I don't want to be annoying with my comments but there may be some binary files that are not executable in the directory. For example .o files. Also consider how perl determines if file is binary or text file - it reads a block of file and check how many "odd" characters (controlcodes, metacharacters) are there. If it's more than 10% of such characters or if there is at least one null character in this block, it's considered binary file. This may produce some wrong results. In general, there is no good way to tell if it's binary or text file. –  Krzysztof Adamski Oct 4 '12 at 19:45
show 7 more comments

In zsh:

setopt extendedglob
chmod +x -- ^*.c

With ksh, or bash with extglob option, or zsh with kshglob option:

chmod +x -- !(*.c)

With ksh93 (probably best to avoid playing with FIGNORE though):

FIGNORE='@(.*|*.c)'
chmod +x -- *

For all, replace *.c with *.* to exclude anything that has a dot.

With zsh, you can do nice things with globbing qualifiers, like:

oftype() [[ $(file -b --mime-type -- $REPLY) = $type ]]
type=application/x-executable; chmod +x -- **/*(.+oftype)

Which would match on regular files "oftype" application/x-executable (recursively descending into subdirectories).

share|improve this answer
add comment

This would also likely work

chmod +x $(find . -type f -print0 | xargs -0 file | grep "ELF [^,;]* executable" |  cut -d: -f1)

You'll still have problems if your files have spaces, tabs, newlines, asterisks, question marks, angle bracket or backslash characters in the names, or if there are too many of them to fit in one command line.

share|improve this answer
1  
It seems to be 64-bit specific. –  Krzysztof Adamski Oct 4 '12 at 15:46
add comment

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.