例えば、私はディレクトリを持っています
/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
ここで、その perl コマンドから関数を作成するとします (~/.bashrc
を使用している場合は、このコマンドを実行するか、シェルの初期化ファイルに追加します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