Làm thế nào để đệ quy chmod tất cả các thư mục ngoại trừ các tập tin?


574

Làm thế nào để chmod 755 tất cả các thư mục nhưng không có tệp (đệ quy)?

Ngược lại, làm thế nào để chmod chỉ các tệp (đệ quy) nhưng không có thư mục?



Câu trả lời:


801

Để đệ quy cho các thư mục đọc và thực thi các đặc quyền:

find /path/to/base/dir -type d -exec chmod 755 {} +

Để đệ quy các tệp đọc đặc quyền:

find /path/to/base/dir -type f -exec chmod 644 {} +

Hoặc, nếu có nhiều đối tượng để xử lý:

chmod 755 $(find /path/to/base/dir -type d)
chmod 644 $(find /path/to/base/dir -type f)

Hoặc, để giảm chmodsinh sản:

find /path/to/base/dir -type d -print0 | xargs -0 chmod 755 
find /path/to/base/dir -type f -print0 | xargs -0 chmod 644

7
Hai ví dụ đầu tiên thất bại cho các thư mục có quá nhiều tệp : -bash: /bin/chmod: Argument list too long. Lệnh cuối cùng hoạt động với nhiều tệp, nhưng khi sử dụng, sudongười ta phải cẩn thận đặt nó trước xargs thay vì chmod:find /path/to/base/dir -type d -print0 | sudo xargs -0 chmod 755
Agargara

2
Cũng cần lưu ý, các lệnh này đã bao gồm thư mục cơ sở. Vì vậy, trong ví dụ trên, dircũng sẽ được đặt thành 755.
CenterOrbit

2
chmod ... $(find /path/to/base/dir -type ...)thất bại cho tên tập tin với không gian trong tên.
Dan Dascalescu

7
Tôi nghĩ rằng phiên bản chính xác nhất (nhưng không nhanh nhất) liên quan đến khoảng trắng và ký hiệu trong tên tệp và số lượng tệp là find /path/to/base/dir -type d -exec chmod 755 {} \;( find /path/to/base/dir -type f -exec chmod 644 {} \;).
Peter K

Lưu ý rằng điều này chỉ đi đến lớp đầu tiên nó có thể đọc. Bạn sẽ phải thực hiện nó nhiều lần để vào sâu hơn trong cây thư mục.
Henk Poley

290

Một lý do phổ biến cho loại điều này là đặt thư mục thành 755 nhưng tệp thành 644. Trong trường hợp này có một cách nhanh hơn một chút so với findví dụ của nik :

chmod -R u+rwX,go+rX,go-w /path

Ý nghĩa:

  • -R = đệ quy;
  • u+rwX = Người dùng có thể đọc, viết và thực hiện;
  • go+rX = nhóm và những người khác có thể đọc và thực hiện;
  • go-w = nhóm và những người khác không thể viết

Điều quan trọng cần lưu ý ở đây là chữ hoa Xhoạt động khác với chữ thường x. Trong hướng dẫn chúng ta có thể đọc:

Các bit thực hiện / tìm kiếm nếu tệp là một thư mục hoặc bất kỳ bit thực hiện / tìm kiếm nào được đặt ở chế độ ban đầu (không sửa đổi).

Nói cách khác, chmod u + X trên một tệp sẽ không đặt bit thực thi; và g + X sẽ chỉ đặt nó nếu nó đã được đặt cho người dùng.


5
-R = đệ quy; u + rwX = Người dùng có thể đọc, viết và thực thi; go + rX = nhóm và những người khác có thể đọc và thực hiện; go-w = nhóm và những người khác không thể viết
släcker

23
Mẫu này sẽ không khắc phục tình huống khi ai đó đã thực hiện chmod -R 777do +Xtùy chọn sẽ không đặt lại các bit thực thi hiện có trên các tệp. Sử dụng -x sẽ thiết lập lại các thư mục và ngăn không cho chúng đi xuống.
Andrew Vit

3
@ ring0: Tôi không có ý định trả lời câu hỏi theo đúng nghĩa đen - nik đã hoàn thành tốt điều đó. Tôi đang chỉ ra một giải pháp rẻ hơn cho trường hợp phổ biến nhất. Và có, bạn có được các quyền khác nhau cho các tệp và thư mục với X, như được giải thích trong các bình luận.
bobince

6
go+rX,go-w-> go=rXphải không?
Pierre de LESPINAY

5
Bạn cũng có thể sử dụng chmod u-x,u+Xkết hợp, v.v., để loại bỏ các bit thực thi cho các tệp, nhưng thêm chúng vào các thư mục.
w0rp

14

Nếu bạn muốn đảm bảo các tệp được đặt thành 644 và có các tệp trong đường dẫn có cờ thực thi, trước tiên bạn sẽ phải xóa cờ thực thi. + X không xóa cờ thực thi khỏi các tệp đã có.

Thí dụ:

chmod -R ugo-x,u+rwX,go+rX,go-w path

Cập nhật: điều này dường như không thành công vì thay đổi đầu tiên (ugo-x) làm cho thư mục không thể thực hiện được, vì vậy tất cả các tệp bên dưới nó không bị thay đổi.


1
Điều này làm việc cho tôi, và tôi không hiểu tại sao nó lại không. (Chắc chắn, nếu bạn đã làm chmod -R ugo-x path, đó có thể là một vấn đề. Nhưng lệnh hoàn chỉnh sẽ thực hiện chmod u+rwXtrên mỗi thư mục trước khi nó cố gắng truy cập vào nó.) Tuy nhiên, tôi tin rằng điều đó chmod R u=rw,go=r,a+X pathlà đủ - và nó ngắn hơn.
Scott

Tôi thấy điều này làm việc đúng; không có vấn đề gì với việc nhập thư mục
Ai đó ở đâu đó vào

4

Tôi quyết định tự viết một kịch bản nhỏ cho việc này.

Tập lệnh chmod đệ quy cho thư mục và / hoặc tệp - Gist :

chmodr.sh

#!/bin/sh
# 
# chmodr.sh
#
# author: Francis Byrne
# date: 2011/02/12
#
# Generic Script for recursively setting permissions for directories and files
# to defined or default permissions using chmod.
#
# Takes a path to recurse through and options for specifying directory and/or 
# file permissions.
# Outputs a list of affected directories and files.
# 
# If no options are specified, it recursively resets all directory and file
# permissions to the default for most OSs (dirs: 755, files: 644).

# Usage message
usage()
{
  echo "Usage: $0 PATH -d DIRPERMS -f FILEPERMS"
  echo "Arguments:"
  echo "PATH: path to the root directory you wish to modify permissions for"
  echo "Options:"
  echo " -d DIRPERMS, directory permissions"
  echo " -f FILEPERMS, file permissions"
  exit 1
}

# Check if user entered arguments
if [ $# -lt 1 ] ; then
 usage
fi

# Get options
while getopts d:f: opt
do
  case "$opt" in
    d) DIRPERMS="$OPTARG";;
    f) FILEPERMS="$OPTARG";;
    \?) usage;;
  esac
done

# Shift option index so that $1 now refers to the first argument
shift $(($OPTIND - 1))

# Default directory and file permissions, if not set on command line
if [ -z "$DIRPERMS" ] && [ -z "$FILEPERMS" ] ; then
  DIRPERMS=755
  FILEPERMS=644
fi

# Set the root path to be the argument entered by the user
ROOT=$1

# Check if the root path is a valid directory
if [ ! -d $ROOT ] ; then
 echo "$ROOT does not exist or isn't a directory!" ; exit 1
fi

# Recursively set directory/file permissions based on the permission variables
if [ -n "$DIRPERMS" ] ; then
  find $ROOT -type d -print0 | xargs -0 chmod -v $DIRPERMS
fi

if [ -n "$FILEPERMS" ] ; then
  find $ROOT -type f -print0 | xargs -0 chmod -v $FILEPERMS
fi

Về cơ bản, nó thực hiện chmod đệ quy nhưng cũng cung cấp một chút linh hoạt cho các tùy chọn dòng lệnh (đặt quyền truy cập thư mục và / hoặc tệp, hoặc loại trừ cả hai nó tự động đặt lại mọi thứ thành 755-644). Nó cũng kiểm tra một vài tình huống lỗi.

Tôi cũng đã viết về nó trên blog của tôi .


2

Để đệ quy cho các thư mục đọc và thực thi các đặc quyền:

find /path/to/base/dir -type d -exec chmod 755 {} \;

Để đệ quy các tệp đọc đặc quyền:

find /path/to/base/dir -type f -exec chmod 644 {} \;

Muộn còn hơn không bao giờ để tôi nâng cấp câu trả lời của nik về mặt chính xác. Giải pháp của tôi chậm hơn, nhưng nó hoạt động với bất kỳ số lượng tệp nào, với bất kỳ ký hiệu nào trong tên tệp và bạn có thể chạy nó với sudo bình thường (nhưng hãy cẩn thận rằng nó có thể phát hiện ra các tệp khác nhau bằng sudo).


Đây là một hạ cấp của câu trả lời của nik . Tại sao bạn tin rằng có bất cứ điều gì sai với câu trả lời của nik?
Scott

@Scott, câu trả lời của nik không thành công với (vey) số lượng lớn tệp.
Peter K

Tôi chắc chắn 99% rằng bạn đã nhầm. Bạn có thể cung cấp bất kỳ bằng chứng để hỗ trợ yêu cầu của bạn?
Scott

Vâng, có vẻ như tôi thực sự sai. tìm ... + dường như chia dòng thành nhiều lệnh, bắt tốt!
Peter K

0

Hãy thử kịch bản python này; nó không yêu cầu sinh sản của các quá trình và chỉ có hai tòa nhà trên mỗi tệp. Ngoài việc triển khai trong C, nó có thể sẽ là cách thực hiện nhanh nhất (tôi cần nó để sửa một hệ thống tệp gồm 15 triệu tệp được đặt thành 777)

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

Trong trường hợp của tôi, một thử / bắt được yêu cầu xung quanh chmod cuối cùng, vì việc chỉnh sửa một số tệp đặc biệt không thành công.


-1

Bạn cũng có thể sử dụng tree:

tree -faid /your_directory | xargs -L1 -I{} bash -c 'sudo chmod 755 "$1"' -- '{}'

và nếu bạn cũng muốn xem thư mục thêm tiếng vang

 tree -faid /your_directory | xargs -L1 -I{} bash -c 'sudo chmod 755 "$1" && echo$1' -- '{}'

@ Hủy 1) Bạn nói đúng về + x Tôi đổi thành 755; 2) 3) để giải quyết vấn đề này, tôi đặt trình giữ chỗ trong một trích dẫn như thế này '{}'
Eduard Florinescu

@Scott Tôi đồng ý đây không phải là câu trả lời hay nhất cũng chậm nhưng sẽ để lại ở đây cho mục đích "didactic", các ý kiến ​​sẽ giải thích thêm, mọi người cũng có thể tìm hiểu về xargscác vấn đề. Các trích dẫn đơn trong tên tệp là một vấn đề đối với nhiều lệnh và tập lệnh, đó là lý do tại sao tôi liệt kê tất cả các tệp có chứa dấu ngoặc đơn và loại bỏ chúng (ý tôi trích dẫn)
Eduard Florinescu

@Scott Trên hệ thống của tôi, tôi đã tìm kiếm tất cả các tệp có chứa dấu ngoặc đơn và thay thế dấu ngoặc đơn
Eduard Florinescu

@Scott Làm thế nào bạn có thể khắc phục thực tế là xargs không giải quyết chính xác các trích dẫn duy nhất?
Eduard Florinescu


-2

Bạn có thể sử dụng tập lệnh bash sau đây làm ví dụ. Hãy chắc chắn cung cấp cho nó quyền thực thi (755). Chỉ cần sử dụng ./autochmod.sh cho thư mục hiện tại hoặc ./autochmod.sh <dir> để chỉ định một thư mục khác.

#!/bin/bash

if [ -e $1 ]; then
    if [ -d $1 ];then
        dir=$1
    else
        echo "No such directory: $1"
        exit
    fi
else
    dir="./"
fi

for f in $(ls -l $dir | awk '{print $8}'); do
    if [ -d $f ];then
        chmod 755 $f
    else
        chmod 644 $f
    fi
done

2
Ồ Quá nhiều vấn đề! (1) Nếu $1không phải là null, nhưng không phải là tên của một thư mục (ví dụ: là một lỗi đánh máy), thì dirsẽ được đặt thành .không có tin nhắn. (2) $1nên "$1"$dirnên "$dir". (3) Bạn không cần phải nói "./"; "."là tốt (và, nói đúng ra, bạn không cần trích dẫn ở đây). (4) Đây không phải là một giải pháp đệ quy. (5) Trên hệ thống của tôi, ls -l … | awk '{ print $8 }'nhận thời gian sửa đổi của tệp. Bạn cần { print $9 }lấy từ đầu tiên của tên tệp. Và thậm chí sau đó, (6) điều này không xử lý tên tệp có khoảng trắng. Tập
Scott

1
Càng và, cuối cùng nhưng không kém phần quan trọng (∞) nếu tập lệnh này nằm trong thư mục hiện tại, nó sẽ chmod tự động đến 644, do đó làm cho chính nó không thể thực thi được!
Scott
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.