When I plug-in an USB stick (FAT) into my Mac or Ubuntu machine, all files have the executable bits set. After having copied the directory structure to my hard disk how do I remove the executable bits recursively just from the files and keep those on the directories?
4 Answers
With GNU chmod (on Ubuntu) single command variant (starting in the current directory):
chmod -R -x+X .
Explanation:
-R- operate recursively-x- remove executable flags for all users+X- set executable flags for all users if it is a directory
In this case the capital X applies only to directories because all executable flags were cleared by -x. Otherwise +X sets executable flag(s) also if the flag was originally set for any of user, group or others.
With BSD chmod (which is present on Mac OS X) you have to do it separately in two commands:
sudo chmod -R -x * && sudo chmod -R +X *
(If you want to include hidden files in the main directory as well, you likely need to change * to . (point), but it is untested.)
-
2On Ubuntu 13.04 a minor tweak is necessary:
chmod -R a-x+X *Eero Aaltonen– Eero Aaltonen2013-08-22 12:37:43 +00:00Commented Aug 22, 2013 at 12:37 -
@EeroAaltonen: Thank you for the note. This could happen if your
umaskdoes not allowxpermission for all. Do you use defaultumaskor did you change it? Could you please send output ofumaskcommand? Besides your solution there is also this possibility:chmod -R a-x,+X *which will set thexpermission according to yourumask. I will update the answer but I would like to check the behaviour in BSD / Mac OS X first.pabouk - Ukraine stay strong– pabouk - Ukraine stay strong2013-08-26 17:22:27 +00:00Commented Aug 26, 2013 at 17:22 -
1@pabouk oopsie! It was actually the CentOs box where I had set my umask to 0007.Eero Aaltonen– Eero Aaltonen2013-08-28 12:15:48 +00:00Commented Aug 28, 2013 at 12:15
-
This is just sad... :( I like the
findvariant in the answer below for it's style of combining simple tools that do One Thing Well.mikezter– mikezter2014-08-05 18:00:12 +00:00Commented Aug 5, 2014 at 18:00 -
3Use
.instead of*if you want this to be applied to all filesJohn Magnolia– John Magnolia2015-04-11 04:49:35 +00:00Commented Apr 11, 2015 at 4:49
If you cd into the correct path first:
find . -type f -exec chmod -x {} \;
or
chmod -x $(find . -type f)
The find finds all files of type 'f' (which means regular file) in the path . and then calls chmod -x on each file. The {} gets substituted for the file name and the \; terminates the chmod command.
-
6If your
findsupports it, use-exec ... \+instead of-exec ... \;— it'll require fewerfork+execs. If it doesn't, usefind ... -print0 | xargs -0 ....ephemient– ephemient2012-06-08 19:49:08 +00:00Commented Jun 8, 2012 at 19:49 -
5I've used this technique, but with "-perm +111" added to the find so it only chmod's ones that have the x-bit set:
find . -type f -perm +111 -exec chmod -x {} \;chrish– chrish2013-05-28 12:54:54 +00:00Commented May 28, 2013 at 12:54 -
5+1 @Matthijs The reason why this is better than pabouk's solution is that this command leaves directories alone, while pabouk's re-sets the executable bit in all directories. There might be some directories which have the executable bit not set, and pabouk's command sets it, while one might wish to leave them as they are.MariusMatutiae– MariusMatutiae2013-11-09 11:14:54 +00:00Commented Nov 9, 2013 at 11:14
-
the 2nd approach will fail for paths that contain spaces.MestreLion– MestreLion2015-09-16 18:50:38 +00:00Commented Sep 16, 2015 at 18:50
-
@ephemient: if your
findsupports-print0I'm pretty sure it will also support-execMestreLion– MestreLion2015-09-16 18:52:47 +00:00Commented Sep 16, 2015 at 18:52
Under Linux and Unix in a terminal window or On Mac OS X, use this in Terminal.app:
find . -type f -print0 | xargs -0 chmod -x
-
1This is, in essence, not different from Matthijs P's answer from 2011.slhck– slhck2013-05-28 11:22:09 +00:00Commented May 28, 2013 at 11:22
-
1Can you remember this command line? I can't.Mike L.– Mike L.2013-05-28 11:48:18 +00:00Commented May 28, 2013 at 11:48
-
See ephemient's comment below Matthijs's answer to see why this answer is useful.PatrickT– PatrickT2016-06-23 18:33:42 +00:00Commented Jun 23, 2016 at 18:33
The chmod -x+X way did not work for me on ubuntu either, thus I wrote this minimal python script:
#!/usr/bin/python3
import os
for par, dirs, files in os.walk('.'):
for d in dirs:
os.chmod(par + '/' + d, 0o755)
for f in files:
os.chmod(par + '/' + f, 0o644)
If there might be any fancy extra stuff such as sockets in your filesystem, you may want to surround the last chmod with a try/catch.