(如何)是否可以仅向那些使用标准 shell 命令和/或 Unix utils 已经拥有 r 权限的人添加 x 权限?

发布于 2025-01-10 04:49:51 字数 573 浏览 0 评论 0原文

我想编写一个可以对多个文件进行操作的 shell 脚本,并且(除其他外)使它们可执行。

问题:这些文件具有不同的权限 - 特别是,有些文件可供所有用户读取,有些文件只能由所有者读取 - 我想为那些拥有读取权限的人添加执行权限(也就是说,如果所有人都可以读取该文件,所有人都应该能够执行它,但如果只有所有者可以读取它,那么只有所有者应该能够执行它)。

我知道如何通过用任意数量的编程语言编写一个小程序并使用几种不同的方法来实现这一目标(从每个代理的权限的简单、直接的条件到巧妙地使用屏蔽和转移权限)位),但我想在“纯”shell 脚本中实现这一点,只使用标准 shell 命令和 Unix utils。

更新:目前有两个答案,两者都提出了有趣的技术(使用 zsh 的 glob 限定符和使用 find),这些技术看起来很接近与我需要的相关,但稍微遗漏了问题的要点,因为我面临的挑战是找到要处理的文件:脚本的用户会告诉它要处理哪些文件在。相反,挑战在于,给定一个特定文件,例如,根据 o+r 是否在该文件上调用 chmod o+x权限已设置。

I want to write a shell script that will operate on multiple files, and (among other things) will make them executable.

The problem: the files have different permissions – in particular, some are readable by all users and some are only readable by the owner – and I want to add the execution permission exactly for those who've got the read permission (that is, if all can read the file, all should be able to execute it, but if only the owner can read it, then only the owner should be able to execute it).

I know how to achieve this by writing a small program in any number of programming languages, and using a few different approaches (from a naive, straight-forward condition on the permissions for each agent to a tricky use of masking and shifting of the permission bits), but I'd like to achieve this in a "pure" shell script, using nothing but standard shell commands and Unix utils.

UPDATE: There are currently two answers, both of which suggesting interesting techniques (using zsh's glob qualifiers, and using find) which seem closely related to what I need, but slightly missing the point of the question, as the challenge I'm facing is not finding which files to work on: the user of the script will tell it which files to work on. Rather, the challenge is, given a specific file, to decide, for example, whether to call chmod o+x on it or not, based on whether the o+r permission is already set.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

听,心雨的声音 2025-01-17 04:49:51

如果使用 zsh 作为 shell,您可以利用 glob 限定符 来限制对具有或不具有特定权限位的文件的匹配:

# chmod all plain files (.) that are world-readable (R) but not world-executable (^X)
zsh$ chmod o+x *(.R^X)
# files that are owner-readable but not owner-executable
zsh$ chmod u+x *(.r^x)
# And groups
zsh$ chmod g+x *(.A^E)

您还可以执行诸如 *(.X^R) 之类的操作来获取全局可执行的文件,但不是世界可读的,或者具有权限(在 ^ 之前)和不具有权限(在 ^ 之后)的其他组合。还有一个 ffspec 限定符,可以更好地控制权限位匹配;有关详细信息,请参阅文档。

要获取目录树中的所有文件而不仅仅是当前目录,请使用 **/* 而不是 *

If using zsh as your shell, you can take advantage of glob qualifiers to limit matches to files with and without specific permission bits:

# chmod all plain files (.) that are world-readable (R) but not world-executable (^X)
zsh$ chmod o+x *(.R^X)
# files that are owner-readable but not owner-executable
zsh$ chmod u+x *(.r^x)
# And groups
zsh$ chmod g+x *(.A^E)

You can also do things like *(.X^R) to get files that are world-executable but not world-readable, or other combinations of having a permission (Before the ^) and not having it (After the ^). There's also a ffspec qualifier for even more control over permission bit matching; see the documentation for details.

To get all files in a directory tree instead of just the current directory, use **/* instead of *.

孤芳又自赏 2025-01-17 04:49:51

到目前为止提供的答案提出了有用的想法,但是,由于它们都没有回答所提出的问题,因此我特此发布我自己的问题的答案。

这个答案提出了三种不同的解决方案,每种解决方案都基于之前发布的答案中建议的不同方法;还有其他未涵盖的方法(我只会提到,在不显示实际代码的情况下,以八进制数形式获取权限的技巧,然后 - 使用某种执行算术/按位计算的机制 - 并计算它用444得到r位,右移2位得到对应的x位,与原来的权限进行或运算,设置结果作为新的权限)。

以下所有解决方案均假设处理文件“$FILE”

解决方案 1 – 如果将当前权限的模式作为文本

这可能是最直接的方法:

permissions=$(stat -f %SA "$FILE")
if [[ $permissions =~ .r........ ]]; then chmod u+x "$FILE"; fi
if [[ $permissions =~ ....r..... ]]; then chmod g+x "$FILE"; fi
if [[ $permissions =~ .......r.. ]]; then chmod o+x "$FILE"; fi

解决方案 2 – 使用 find,利用 -perm-exec 选项

这种方法使用 find 不是查找多个文件,而是查找多个文件要么找到给定的文件(如果它具有一定的权限),要么不找到查找任何内容(否则),并在找到文件时设置匹配的所需权限(否则不执行任何操作):

find "$FILE" -perm -u=r -exec chmod u+x {} \;
find "$FILE" -perm -g=r -exec chmod g+x {} \;
find "$FILE" -perm -o=r -exec chmod o+x {} \;

这三种情况可以轻松组合成一个 for 循环:

for w in u g o; find "$FILE" -perm -$w=r -exec chmod $w+x {} \;; done

解决方案3(仅限 zsh) – 使用 glob 限定符

此方法仅在 "$FILE" 上运行每个相关的 chmod 命令如果它已经匹配相应的权限。注意<代码>||添加 : 是为了避免在没有匹配项时出现错误,即文件没有相应的权限(另请注意 zsh 仍然会发出 no matches find在这种情况下发出警告):

chmod u+x "$FILE"(r) || :
chmod g+x "$FILE"(A) || :
chmod o+x "$FILE"(R) || :

The answers provided so far present useful ideas, but, as none of them answers the question as asked, I am hereby posting an answer to my own question.

This answer presents three different solutions, each based on a different approach suggested in the previously posted answers; there are other ways too which are not covered (I'll only mention, without showing the actual code, the trick of getting the permissions as an octal number, and then – using some mechanism of performing arithmetic/bit-wise calculations – anding it with 444 to get the r bits, shifting right 2 bits to get the corresponding x bits, oring with the original permissions, and setting the result as the new permissions).

All of the solutions below assume working on the file "$FILE".

Solution 1 – ifing on the pattern of the current permissions as text

This is perhaps the most straightforward approach:

permissions=$(stat -f %SA "$FILE")
if [[ $permissions =~ .r........ ]]; then chmod u+x "$FILE"; fi
if [[ $permissions =~ ....r..... ]]; then chmod g+x "$FILE"; fi
if [[ $permissions =~ .......r.. ]]; then chmod o+x "$FILE"; fi

Solution 2 – using find, taking advantage of the -perm and -exec options

This approach uses find not to find multiple files, but rather to either find the given file (in case it has a certain permission) or to not find anything (otherwise), and to set the matching desired permission in case the file is found (and do nothing otherwise):

find "$FILE" -perm -u=r -exec chmod u+x {} \;
find "$FILE" -perm -g=r -exec chmod g+x {} \;
find "$FILE" -perm -o=r -exec chmod o+x {} \;

The three cases can easily be combined into a single for loop:

for w in u g o; find "$FILE" -perm -$w=r -exec chmod $w+x {} \;; done

Solution 3 (zsh only) – using glob qualifiers

This approach runs each of the relevant chmod commands on "$FILE" only in case it already matches the corresponding permission. Note || : is added to avoid errors in case there's no match, i.e. if the file does not have the corresponding permission (also note zsh still emits a no matches found warning in this case):

chmod u+x "$FILE"(r) || :
chmod g+x "$FILE"(A) || :
chmod o+x "$FILE"(R) || :
情栀口红 2025-01-17 04:49:51

这可能不是最有效的方法,但我真的很喜欢 find 命令的直观 API。

以下命令查找当前目录(.)中该组或所有用户可读的所有文件和目录:

find . -perm /go=r

并且此命令查找所有者可读但该组或所有用户不可读的所有文件和目录用户:

find . -perm /u=r ! -perm /go=r

找到要处理的文件后,您可以添加 -exec 参数来对每个匹配项执行命令。
例如,以下命令将在仅所有者可读的所有文件和目录上设置所有者的可执行位:

find . -perm /u=r ! -perm /go=r -exec chmod u+x {} \;

该行的结尾很奇怪,但完全按照所示输入它,它应该可以工作。

此命令将为组和其他人可读的所有文件和目录设置“组”和“其他”的可执行位:

find . -perm /go=r -exec chmod go+x {} \;

所有这些命令都在当前目录中递归搜索。您可以通过将 . 替换为另一个路径来指定任意其他目录。

您还可以使用 -maxdepth N 指定搜索的深度。

编辑:
如果您想处理单个指定文件,可以使用以下脚本。它使用 stat 命令检查文件的权限,该命令以类似于 ls -l 显示的格式返回权限,例如 -rw-r--r- -

myfile="/tmp/abc"

permissions="$(stat -c %A $myfile)"
if [[ "$permissions" =~ ^....r.....$ ]] || [[ "$permissions" =~ ^.......r..$ ]]; then
    # file is readable by group and/or others
    # set executable bit for owner, group and others
    chmod a+x "$myfile"
elif [[ "$permissions" =~ ^.r........$ ]]; then
    # file is note readable by group or others
    # Set executable bit for owner only
    chmod u+x "$myfile"
fi

该脚本适用于 bash 和 zsh。

This is probably not the most efficient way to do it, but I really like the find command for its intuitive API.

The following command finds all files and directories in the current directory (the .) that are readable by the group or by all users:

find . -perm /go=r

And this command finds all files and directories that are readable by the owner but NOT readable by the group or by all users:

find . -perm /u=r ! -perm /go=r

Once you find the files you want to process, you can add an -exec argument to execute a command on each of the matches.
For example, the following command would set owner's executable bit on all files and directories that are readable by the owner only:

find . -perm /u=r ! -perm /go=r -exec chmod u+x {} \;

The end of the line is quite weird but enter it exactly as shown and it should work.

And this command would set the executable bits for "group" and "others" on all files and directories that are readable by group and others:

find . -perm /go=r -exec chmod go+x {} \;

All these commands search recursively in the current directory. You can specify an arbitrary other directory by replacing . with another path.

You can also specify how deep the searching should go with -maxdepth N.

Edit:
In case you want to process a single specified file, you can use the following script. It checks file's permissions by using the stat command which returns the permissions in format similar to what ls -l displays, for example -rw-r--r--.

myfile="/tmp/abc"

permissions="$(stat -c %A $myfile)"
if [[ "$permissions" =~ ^....r.....$ ]] || [[ "$permissions" =~ ^.......r..$ ]]; then
    # file is readable by group and/or others
    # set executable bit for owner, group and others
    chmod a+x "$myfile"
elif [[ "$permissions" =~ ^.r........$ ]]; then
    # file is note readable by group or others
    # Set executable bit for owner only
    chmod u+x "$myfile"
fi

This script works in bash and zsh.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文