วิธีการทำซ้ำ chmod ไดเรกทอรีทั้งหมดยกเว้นไฟล์?


574

วิธีการ chmod 755 ไดเรกทอรีทั้งหมด แต่ไม่มีไฟล์ (เรียกซ้ำ)

ตรงกันข้ามวิธีการ chmod เฉพาะไฟล์ (เรียกซ้ำ) แต่ไม่มีไดเรกทอรี?



คำตอบ:


801

หากต้องการให้สิทธิ์การอ่านและเรียกใช้งานไดเรกทอรีซ้ำ ๆ:

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

หากต้องการให้สิทธิ์การอ่านไฟล์ซ้ำ ๆ:

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

หรือหากมีวัตถุจำนวนมากที่ต้องดำเนินการ:

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

หรือเพื่อลดการchmodวางไข่:

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
-bash: /bin/chmod: Argument list too longสองตัวอย่างแรกล้มเหลวสำหรับไดเรกทอรีที่มีไฟล์จำนวนมากเกินไป: คำสั่งสุดท้ายใช้งานได้กับไฟล์จำนวนมาก แต่เมื่อใช้sudoอย่างใดอย่างหนึ่งจะต้องระมัดระวังที่จะนำมันก่อนที่จะ xargs แทน chmod:find /path/to/base/dir -type d -print0 | sudo xargs -0 chmod 755
Agargara

2
นอกจากนี้เมื่อต้องการทราบคำสั่งเหล่านี้รวม dir ฐาน ดังนั้นในตัวอย่างข้างต้นdirจะได้รับการตั้งค่าเป็น 755
CenterOrbit

2
chmod ... $(find /path/to/base/dir -type ...)ล้มเหลวสำหรับชื่อไฟล์ที่มีช่องว่างในชื่อ
Dan Dascalescu

7
ฉันคิดว่ารุ่นที่ถูกต้องที่สุด (แต่ไม่เร็วที่สุด) สำหรับช่องว่างและสัญลักษณ์ในชื่อไฟล์และจำนวนไฟล์คือfind /path/to/base/dir -type d -exec chmod 755 {} \;( find /path/to/base/dir -type f -exec chmod 644 {} \;)
ปีเตอร์ K

โปรดทราบว่าสิ่งนี้จะไปที่เลเยอร์แรกเท่านั้นที่สามารถอ่านได้ คุณจะต้องดำเนินการหลาย ๆ ครั้งเพื่อให้ลึกเข้าไปในแผนผังทรี
Henk Poley

290

สาเหตุทั่วไปของสิ่งนี้คือการตั้งค่าไดเรกทอรีเป็น 755 แต่ไฟล์เป็น 644 ในกรณีนี้มีวิธีที่เร็วกว่าfindตัวอย่างของ nik เล็กน้อย:

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

ความหมาย:

  • -R = เรียกซ้ำ;
  • u+rwX = ผู้ใช้สามารถอ่านเขียนและดำเนินการ;
  • go+rX = กลุ่มและอื่น ๆ สามารถอ่านและดำเนินการได้;
  • go-w = กลุ่มและอื่น ๆ ไม่สามารถเขียนได้

สิ่งสำคัญที่ต้องทราบว่านี่คือตัวพิมพ์ใหญ่ทำหน้าที่แตกต่างกันเป็นตัวพิมพ์เล็กX xในคู่มือเราสามารถอ่าน:

บิตเรียกใช้ / ค้นหาหากไฟล์เป็นไดเรกทอรีหรือบิตเรียกใช้ / ค้นหาใด ๆ ตั้งอยู่ในโหมดดั้งเดิม (ไม่ได้แก้ไข)

อีกนัยหนึ่ง chmod u + X บนไฟล์จะไม่ตั้งค่าบิตเรียกใช้งาน และ g + X จะตั้งค่าก็ต่อเมื่อมันได้ตั้งไว้สำหรับผู้ใช้แล้ว


5
-R = ซ้ำ; u + rwX = ผู้ใช้สามารถอ่านเขียนและดำเนินการ; go + rX = กลุ่มและคนอื่น ๆ สามารถอ่านและดำเนินการได้; go-w = กลุ่มและคนอื่น ๆ ไม่สามารถเขียนได้
släcker

23
รูปแบบนี้จะไม่แก้ไขสถานการณ์เมื่อมีคนทำchmod -R 777เนื่องจาก+Xตัวเลือกจะไม่รีเซ็ตบิตรันที่มีอยู่ในไฟล์ การใช้ -x จะรีเซ็ตไดเรกทอรีและป้องกันไม่ให้ลงไปในพวกเขา
Andrew Vit

3
@ ring0: ฉันไม่ได้ตั้งใจที่จะตอบคำถามอย่างแท้จริงตามที่โพสต์ - nik ได้ทำไปแล้วอย่างสมบูรณ์แบบดี ฉันกำลังชี้ทางออกที่ถูกกว่าสำหรับกรณีที่พบบ่อยที่สุด และใช่คุณจะได้รับการอนุญาตที่แตกต่างกันสำหรับไฟล์และไดเรกทอรีXตามที่อธิบายไว้ในความคิดเห็น
bobince

6
go+rX,go-w-> go=rXใช่ไหม
Pierre de LESPINAY

5
นอกจากนี้คุณยังสามารถใช้chmod u-x,u+Xร่วมกันเพื่อลบ execute bits สำหรับไฟล์ได้ แต่เพิ่มไว้ในไดเรกทอรี่
w0rp

14

หากคุณต้องการตรวจสอบให้แน่ใจว่าไฟล์ถูกตั้งค่าเป็น 644 และมีไฟล์ในพา ธ ที่มีแฟล็ก execute คุณจะต้องลบแฟล็ก execute ก่อน + X ไม่ได้ลบแฟลกดำเนินการออกจากไฟล์ที่มีอยู่แล้ว

ตัวอย่าง:

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

อัปเดต: สิ่งนี้ดูเหมือนจะล้มเหลวเนื่องจากการเปลี่ยนแปลงครั้งแรก (ugo-x) ทำให้ไดเรกทอรีไม่สามารถดำเนินการได้ดังนั้นไฟล์ทั้งหมดที่อยู่ภายใต้จะไม่เปลี่ยนแปลง


1
มันใช้งานได้สำหรับฉันและฉันไม่เห็นว่าทำไมจึงไม่เป็นเช่นนั้น (แน่นอนว่าถ้าคุณทำเพียงแค่chmod -R ugo-x pathนั้นอาจเป็นปัญหา แต่คำสั่งทั้งหมดจะทำchmod u+rwXในแต่ละไดเรกทอรีก่อนที่จะพยายามที่จะลงไป) แต่ฉันเชื่อว่าchmod R u=rw,go=r,a+X pathเพียงพอ - และมันสั้นลง
สกอตต์

ฉันพบว่าสิ่งนี้ทำงานได้อย่างถูกต้อง ไม่มีปัญหากับการป้อนไดเรกทอรี
บางคนอยู่ที่ไหนสักแห่ง

4

ฉันตัดสินใจที่จะเขียนสคริปต์เล็กน้อยสำหรับตัวฉันเอง

สคริปต์ chmod แบบเรียกซ้ำสำหรับ dirs และ / หรือไฟล์ - สรุปสาระสำคัญ :

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

มันเป็นพื้นเรียก chmod ซ้ำ แต่ยังให้ความยืดหยุ่นเล็กน้อยสำหรับตัวเลือกบรรทัดคำสั่ง (ตั้งค่าไดเรกทอรีและ / หรือสิทธิ์ของไฟล์หรือไม่รวมทั้งมันจะรีเซ็ตทุกอย่างเพื่อ 755-644 โดยอัตโนมัติ) นอกจากนี้ยังตรวจสอบสถานการณ์ข้อผิดพลาดเล็กน้อย

ฉันยังเขียนเกี่ยวกับเรื่องนี้ในบล็อกของฉัน


2

หากต้องการให้สิทธิ์การอ่านและเรียกใช้งานไดเรกทอรีซ้ำ ๆ:

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

หากต้องการให้สิทธิ์การอ่านไฟล์ซ้ำ ๆ:

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

ดีกว่าไม่สายให้ฉันอัพเกรดคำตอบของ Nik ที่ด้านความถูกต้อง โซลูชันของฉันช้าลง แต่ใช้งานได้กับไฟล์จำนวนเท่าใดก็ได้พร้อมกับสัญลักษณ์ใด ๆ ในชื่อไฟล์และคุณสามารถเรียกใช้ด้วย sudo ได้ตามปกติ (แต่ระวังว่ามันอาจค้นพบไฟล์ที่แตกต่างกันด้วย sudo)


นี่คือการลดระดับของคำตอบของนิก ทำไมคุณถึงเชื่อว่ามีอะไรผิดปกติกับคำตอบของนิก?
สกอตต์

@Scott คำตอบของ nik ล้มเหลวด้วย (vey) ไฟล์จำนวนมาก
ปีเตอร์ K

ฉันแน่ใจว่า 99% ว่าคุณเข้าใจผิด คุณสามารถให้หลักฐานเพื่อสนับสนุนข้อเรียกร้องของคุณได้หรือไม่?
สกอตต์

ใช่ดูเหมือนว่าฉันผิดแน่นอน หา ... + ดูเหมือนจะแบ่งบรรทัดออกเป็นหลายคำสั่งจับดี!
ปีเตอร์ K

0

ลองใช้สคริปต์ python นี้ มันไม่จำเป็นต้องวางไข่ของกระบวนการและทำเพียงสอง syscalls ต่อไฟล์ นอกเหนือจากการใช้งานใน C มันอาจจะเป็นวิธีที่เร็วที่สุดในการทำมัน (ฉันต้องการมันเพื่อแก้ไขระบบไฟล์ 15 ล้านไฟล์ซึ่งทั้งหมดถูกตั้งค่าเป็น 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)

ในกรณีของฉันจำเป็นต้องมีการลอง / จับรอบ chmod ล่าสุดเนื่องจาก chmodding บางไฟล์พิเศษล้มเหลว


-1

คุณยังสามารถใช้tree:

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

และถ้าคุณต้องการที่จะดูโฟลเดอร์เพิ่ม echo

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

@Scott 1) ​​คุณพูดถูก + ฉันเปลี่ยนไปเป็น 755; 2) 3) เพื่อแก้ปัญหานี้ฉันวางตัวแทนไว้ในเครื่องหมายคำพูดเดียวเช่นนี้ '{}'
Eduard Florinescu

@Scott ฉันเห็นด้วยว่านี่ไม่ใช่คำตอบที่ดีที่สุด แต่ช้ามาก แต่จะทิ้งไว้ที่นี่เพื่อ "การสอน" และความคิดเห็นจะอธิบายเพิ่มเติมอีกทั้งผู้คนสามารถเรียนรู้เกี่ยวกับxargsปัญหาได้ ราคาเดียวในชื่อไฟล์เป็นตัวปัญหาสำหรับหลายคำสั่งและสคริปต์ที่ว่าทำไมฉันแสดงไฟล์ทั้งหมดที่มีราคาเดียวและลบออกพวกเขา (คำพูดที่ผมหมายถึง)
เอดูอาร์ Florinescu

@Scott ในระบบของฉันฉันค้นหาไฟล์ทั้งหมดที่มีเครื่องหมายคำพูดเดี่ยวและแทนที่คำพูดเดี่ยว
Eduard Florinescu

@Scott คุณจะแก้ไขความจริงที่ว่า xargs ไม่สามารถแก้คำพูดที่ถูกต้องได้อย่างไร?
Eduard Florinescu

ขอให้เรายังคงอภิปรายนี้ในการแชท
Eduard Florinescu

-2

คุณสามารถใช้สคริปต์ทุบตีต่อไปนี้เป็นตัวอย่าง ตรวจสอบให้แน่ใจว่าได้ให้สิทธิ์อนุญาตปฏิบัติการ (755) เพียงใช้. / autochmod.sh สำหรับไดเรกทอรีปัจจุบันหรือ. / autochmod.sh <dir> เพื่อระบุที่แตกต่างกัน

#!/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
ว้าว! ปัญหามากมาย! (1) ถ้า$1ไม่ใช่โมฆะ แต่ไม่ใช่ชื่อของไดเรกทอรี (เช่นเป็นตัวพิมพ์ใหญ่) จากนั้นdirให้ตั้งค่าเป็น.ไม่มีข้อความ (2) $1ควรจะเป็น"$1"และควรจะเป็น$dir "$dir"(3) คุณไม่จำเป็นต้องพูด"./"; "."ไม่เป็นไร (และพูดอย่างเคร่งครัดคุณไม่จำเป็นต้องมีคำพูดที่นี่) (4) นี่ไม่ใช่วิธีเรียกซ้ำ (5) ในระบบของฉันls -l … | awk '{ print $8 }'รับเวลาการแก้ไขของไฟล์ คุณต้อง{ print $9 }ได้คำแรกของชื่อไฟล์ และถึงตอนนั้น (6) สิ่งนี้ไม่ได้จัดการชื่อไฟล์ที่มีพื้นที่สีขาว …
สกอตต์

1
... และสุดท้าย แต่ไม่น้อย (∞) ถ้าสคริปต์นี้อยู่ในไดเรกทอรีปัจจุบันมันจะchmod ตัวเองเป็น 644 จึงทำให้ตัวเองไม่สามารถทำงาน!
สกอตต์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.