我的文件结构因故障软件的所有权更改而损坏。我有一个几乎完全相同的结构,来自之前的备份。
我想要完成的是镜像文件所有权,以解决此问题。
我有以下脚本,但由于文件名/目录上的空格而失败:
IFS=$'\n'
D1=/Users/emarques/temp/test\ 1
D2=/Users/emarques/temp/test\ 2
for entry in $(find $D1 -exec stat -f "%N:%u:%g" {} \;); do
$(echo \"$entry\" | \
tr -d '"' | \
sed 's#'$D1'#'$D2'#' | \
awk -F: '{printf ("chown %s %s\n", $2 ":" $3, "\"" $1 "\"")}')
done
输出
-bash: chown 0:20 "/Users/emarques/temp/test 2": No such file or directory
-bash: chown 501:20 "/Users/emarques/temp/test 2/1": No such file or directory
-bash: chown 501:20 "/Users/emarques/temp/test 2/1/a": No such file or directory
-bash: chown 501:20 "/Users/emarques/temp/test 2/1/b": No such file or directory
-bash: chown 501:20 "/Users/emarques/temp/test 2/2": No such file or directory
-bash: chown 501:20 "/Users/emarques/temp/test 2/2/a": No such file or directory
-bash: chown 502:20 "/Users/emarques/temp/test 2/2/b": No such file or directory
-bash: chown 501:20 "/Users/emarques/temp/test 2/3": No such file or directory
-bash: chown 502:80 "/Users/emarques/temp/test 2/a": No such file or directory
-bash: chown 502:80 "/Users/emarques/temp/test 2/b": No such file or directory
-bash: chown 501:20 "/Users/emarques/temp/test 2/c": No such file or directory
我向IT同事请求帮助,因为我还没弄清楚如何完成这项工作。任何意见都非常感谢。
答案 0 :(得分:2)
某些版本的chown
支持“参考文件”选项:
--reference=RFILE
use RFILE's owner and group rather than specifying OWNER:GROUP
values
如果您的chown
有,请执行:
cd "/Users/emarques/temp/test 1"
find . -exec sh -c 'chown --reference="$1" "/Users/emarques/temp/test 2/$1"' _ {}
或者,稍微复杂一点,但可能更有效:
cd "/Users/emarques/temp/test 1"
find . -exec sh -c 'for f; do chown --reference="$f" "/Users/emarques/temp/test 2/$f"; done' _ {} +
你不必再担心引用了。
如果您的chown
不支持参考文件,则:
cd "/Users/emarques/temp/test 1"
shopt -s globstar dotglob
for f in **/*
do
chown "$(stat -f "%u:%g" "$f")" "/Users/emarques/temp/test 2/$f"
done
从第一个目录开始,你可以省去很多麻烦,因为你可以免费获得相对路径。
答案 1 :(得分:2)
从stat
命令的选项和用户目录的结构,我怀疑你在macOS中运行它,这意味着你可能只限于bash v3和你的工具(比如stat)和chown)使用BSD选项。
乍一看,这里有一些你不应该做的事情。
$D1
中添加了一个空格,但随后是find $D1
而不是find "$D1"
。请注意,echo \"$entry\"
包含一个未加引号的变量。你需要引用变量的地方是它们可能被空格分割的任何地方。由于有时候很难知道,所以到处都引用它们。for entry in $(find ...)
并且find
的结果包含空格时,您不太可能获得所需的结果。有关原因的说明,请查看ParsingLs页面。 (您正试图通过设置$IFS
来缓解此问题,但这会使其他事情变得复杂。)除此之外,您可以使用多种方法之一。
1 - 在find
中运行所有内容。
您已了解find
命令的-exec
选项。您可以在find
中加载更多内容。以下是未经测试的:
cd "$D1"
find . -exec sh -c 'chown $(stat -f "%u:%g" {}) $0/{}' "$D2" \;
2 - 使用更好的分隔符。
find
命令有-print0
选项,导致文件由空值而不是空格分隔。这也是未经测试的:
find "$D1" -print0 | while read -d$'\0' file; do
chown $(stat -f '%u:%g' "$file") "$D2/$file"
done
done
3 - 如果可以,请避免查找,使用globstar。
这仅适用于bash 4可用,因为bash 3(macOS中的默认值)不包含globstar。 (如果需要,您可以使用macports或homebrew安装bash 4.)
D1="/Users/emarques/temp/test 1"
D2="/Users/emarques/temp/test 2"
shopt -s globstar
# If there are files in D2 that might not appear in D1...
cd "$D1"
for file in **; do
chown $(stat -f '%u:%g' "$file") "$D2/$file"
done
# Or if there are files in D1 which might be missing from D2...
cd "$D2"
for file in **; do
chown $(stat -f '%u:%g' "$D1/$file") "$file"
done
这里有两个起点,以防文件列表完全匹配。如果它们匹配,则两个选项应该是等效的。