하위 디렉터리에서 루트로 어떻게 이동합니까?

하위 디렉터리에서 루트로 어떻게 이동합니까?

예를 들어 디렉토리가 있습니다.

/path/to/directory

하위 디렉터리의 권한을 뭔가로 설정하고 싶습니다. 이것은 쉬워요:

find /path/to/directory -type d -exec chmod something {} +

그런데 어떻게 반대로 할 수 있나요? 동일한 권한을 설정해야 합니다.

/path

그리고

/path/to

그리고

/path/to/directory

나는 이와 같은 디렉토리를 많이 가지고 있으며 스크립팅 솔루션을 찾고 있습니다.

답변1

에 도달할 때까지 위쪽으로 반복 /하고 각 디렉터리에 대한 함수를 호출합니다.

#!/bin/sh

function mangleperms {
    echo DEBUG would chmod 755 "$1"
}

function walktoroot {
    DIR="$1"
    HANDLE="$2"
    if [ "$DIR" = "/" ]; then
        return
    fi
    "$HANDLE" "$DIR"

    # recursion (noun): see recursion
    PARENTDIR=`dirname "$DIR"`
    walktoroot "$PARENTDIR" "$HANDLE"
}

if [ -z "$1" ]; then
    echo >&2 "Usage: walktoroot dir"
    exit 1
fi
# TODO probably more edge cases on relative dirs, though there are means
# to fully qualify those
if [ "$1" = "." ]; then
    DIR=`pwd`
else
    DIR=$1
fi

walktoroot "$DIR" mangleperms

예:

$ pwd
/var/tmp/a/b/c
$ /home/jdoe/walktoroot .
DEBUG would chmod 755 /var/tmp/a/b/c
DEBUG would chmod 755 /var/tmp/a/b
DEBUG would chmod 755 /var/tmp/a
DEBUG would chmod 755 /var/tmp
DEBUG would chmod 755 /var
$ 

답변2

우리 는 find이것을 다음과 같이 할 수 있습니다:

find /path/to/dir -type d -prune -exec chmod 755 {} \; -exec sh -c '
   while { set -- "${1%/*}"; case $1 in "" ) break ;; esac; }
   do find "$1" -type d -prune -exec chmod 755 \{\} \;; done
' {} {} \;

함수 를 사용하는 또 다른 방법 recursive:

   fx() {
      case $1 in ?* ) chmod 755 "$1"; fx "${1%/*}" ;; esac
   }
   # and then...
   fx /path/to/dir

답변3

음, 경로는 단지 문자열일 뿐입니다. 따라서 이를 분할 /하고 각 결과에 명령을 적용할 수 있습니다. 예를 들어, 작은 Perl 한 줄짜리 코드를 사용하여 상위 경로를 인쇄할 수 있습니다.

$ path=/path/to/some/deeply/buried/thing
$ echo "$path" | perl -F"/" -lane 'for(1..$#F){print join("/",@F[0..$_])}'
/path
/path/to
/path/to/some
/path/to/some/deeply
/path/to/some/deeply/buried
/path/to/some/deeply/buried/thing

~/.bashrc이제 해당 perl 명령으로 기능을 만드는 경우( 사용 중인 경우 이 명령을 실행하거나 셸의 초기화 파일에 추가 bash):

pexpand(){ 
   printf '%s\n' "$1" | perl -F"/" -lane 'for(1..$#F){print join("/",@F[0..$_])}'; 
}

이제 다음과 같이 사용할 수 있습니다.

$ pexpand $path
/path
/path/to
/path/to/some
/path/to/some/deeply
/path/to/some/deeply/buried
/path/to/some/deeply/buried/thing

그리고 다음을 사용하여 해당 경로의 각 디렉터리에서 명령을 실행할 수 있습니다.

chmod 733 "$(pexpand "$path")"

경로에 개행 문자가 포함될 수 있으면 위의 접근 방식은 실패합니다. 보다 강력한 버전은 다음과 같습니다.

pexpand(){ 
 perl -le '@F=split(/\//, $ARGV[0]); 
           for(1..$#F){printf "%s\0",join("/",@F[0..$_])}' "$1"; 
}  

하지만 이는 사용하기가 더 번거롭습니다.

pexpand "$path" | while IFS= read -r -d '' d; do chmod 733 "$d"; done

따라서 임의 입력에 대해 이 작업이 필요한 경우 대신 경로와 명령을 모두 입력으로 사용하는 작은 스크립트를 작성하는 것이 좋습니다.

#!/usr/bin/perl

my $comm = $ARGV[0] || die "At least 2 arguments are necessary\n";
my $path = $ARGV[1] || die "At least 2 arguments are necessary\n";

my @paths=split(/\//, $path);
for (1..$#paths) {
    system("$comm \"" . join("/",@paths[0..$_]) . "\"");
}

해당 스크립트를 foo.pl의 디렉터리에 무언가(또는 무엇이든) 로 저장하고 $PATH실행 가능하게 만들면( chmod a+x ~/bin/foo.pl) 이제 다음과 같이 실행할 수 있습니다.

foo.pl  "chmod 700" /path/to/some/deeply/buried/thing

관련 정보