如何从子目录遍历到根目录?

如何从子目录遍历到根目录?

例如我有一个目录

/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 命令创建一个函数(运行此命令或将其添加到 shell 的初始化文件中 —~/.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

相关内容