Jak rekurencyjnie usunąć bit wykonywalny z plików (nie katalogów)

73

Kiedy podłączam pamięć USB (FAT) do komputera Mac lub Ubuntu, wszystkie pliki mają ustawione bity wykonywalne. Jak po skopiowaniu struktury katalogów na dysk twardy mogę rekurencyjnie usunąć bity wykonywalne tylko z plików i zachować je w katalogach?

Mike L.
źródło

Odpowiedzi:

132

W przypadku GNU chmod(na Ubuntu) wariant pojedynczego polecenia (począwszy od bieżącego katalogu):

chmod -R -x+X .

Wyjaśnienie:

  • -R - działają rekurencyjnie
  • -x - usuń flagi wykonywalne dla wszystkich użytkowników
  • +X - ustaw flagi wykonywalne dla wszystkich użytkowników, jeśli jest to katalog

W tym przypadku kapitał Xdotyczy tylko katalogów, ponieważ wszystkie flagi wykonywalne zostały usunięte przez -x. W przeciwnym razie +Xustawia flagi wykonywalne, jeśli flaga została pierwotnie ustawiona dla dowolnego użytkownika, grupy lub innych osób.

W BSD chmod(który jest obecny w Mac OS X) musisz to zrobić osobno za pomocą dwóch poleceń:

sudo chmod -R -x * && sudo chmod -R +X *

(Jeśli chcesz również dołączyć ukryte pliki do głównego katalogu, prawdopodobnie musisz zmienić * na. (Punkt), ale nie jest to testowane).

pabouk
źródło
W systemie Ubuntu 13.04 konieczna jest drobna poprawka:chmod -R a-x+X *
Eero Aaltonen
@EeroAaltonen: Dziękuję za notatkę. Może się to zdarzyć, jeśli umasknie zezwalasz xna wszystkie uprawnienia. Używasz domyślnej umasklub zmieniłeś ją? Czy możesz wysłać wynik umaskpolecenia? Oprócz twojego rozwiązania istnieje również taka możliwość: chmod -R a-x,+X *która ustali xpozwolenie według twojego umask. Zaktualizuję odpowiedź, ale najpierw chciałbym sprawdzić zachowanie w BSD / Mac OS X.
pabouk
@pabouk oopsie! W rzeczywistości była to skrzynka CentO, w której ustawiłem swój umask na 0007.
Eero Aaltonen
To jest po prostu smutne ... :( Podoba mi się findwariant w poniższej odpowiedzi ze względu na styl łączenia prostych narzędzi, które wykonują One Thing Well.
Mikezter
2
Użyj .zamiast, *jeśli chcesz, aby to dotyczyło wszystkich plików
John Magnolia
46

Jeśli najpierw wpiszesz właściwą ścieżkę:

find . -type f -exec chmod -x {} \;

lub

chmod -x $(find . -type f)

Find znajduje wszystkie ścieżki typu „f” (co oznacza zwykły plik) na ścieżce. a następnie wywołuje chmod -x na każdym pliku. {} Zostaje zastąpione nazwą pliku i \; kończy polecenie chmod.

Matthijs P.
źródło
6
Jeśli findto obsługuje, użyj -exec ... \+zamiast -exec ... \;- będzie wymagało mniej fork+ execs. Jeśli nie, użyj find ... -print0 | xargs -0 ....
ephemient
5
Użyłem tej techniki, ale z „-perm +111” dodanym do znaleziska, więc tylko chmod mają te ustawione na x-bit:find . -type f -perm +111 -exec chmod -x {} \;
chrish
4
+1 @Matthijs Powodem, dla którego jest to lepsze niż rozwiązanie pabouk, jest to, że to polecenie pozostawia katalogi w spokoju, podczas gdy pabouk ponownie ustawia bit wykonywalny we wszystkich katalogach. Mogą istnieć niektóre katalogi, w których nie ma ustawionego bitu wykonywalnego, a polecenie pabouk ustawia go, podczas gdy ktoś może chcieć zostawić je takimi, jakie są.
MariusMatutiae
drugie podejście zakończy się niepowodzeniem dla ścieżek zawierających spacje.
MestreLion
@ephemient: jeśli findwspierasz -print0, jestem prawie pewien, że będzie również obsługiwał-exec
MestreLion
3

W systemach Linux i Unix w oknie terminala lub w systemie Mac OS X użyj tego w Terminal.app:

find . -type f -print0 | xargs -0 chmod -x
użytkownik227317
źródło
1
Zasadniczo nie różni się to od odpowiedzi Matthijsa P. z 2011 r.
slhck
Czy pamiętasz tę linię poleceń? Nie mogę
Mike L.
Zobacz komentarz ephemienta poniżej odpowiedzi Matthijsa, aby zobaczyć, dlaczego ta odpowiedź jest przydatna.
PatrickT,
2

Ten chmod -x+Xsposób również nie działał dla mnie na Ubuntu, dlatego napisałem ten minimalny skrypt Pythona:

#!/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)

Jeśli mogą być jakieś wymyślne dodatkowe rzeczy, takie jak gniazda w twoim systemie plików, możesz otoczyć ostatni chmod try / catch.

mic_e
źródło