(如何)是否可以仅向那些使用标准 shell 命令和/或 Unix utils 已经拥有 r 权限的人添加 x 权限?
我想编写一个可以对多个文件进行操作的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果使用
zsh
作为 shell,您可以利用 glob 限定符 来限制对具有或不具有特定权限位的文件的匹配:您还可以执行诸如
*(.X^R)
之类的操作来获取全局可执行的文件,但不是世界可读的,或者具有权限(在^
之前)和不具有权限(在^
之后)的其他组合。还有一个f
fspec 限定符,可以更好地控制权限位匹配;有关详细信息,请参阅文档。要获取目录树中的所有文件而不仅仅是当前目录,请使用
**/*
而不是*
。If using
zsh
as your shell, you can take advantage of glob qualifiers to limit matches to files with and without specific permission bits: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 af
fspec 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*
.到目前为止提供的答案提出了有用的想法,但是,由于它们都没有回答所提出的问题,因此我特此发布我自己的问题的答案。
这个答案提出了三种不同的解决方案,每种解决方案都基于之前发布的答案中建议的不同方法;还有其他未涵盖的方法(我只会提到,在不显示实际代码的情况下,以八进制数形式获取权限的技巧,然后 - 使用某种执行算术/按位计算的机制 - 并计算它用
444
得到r
位,右移2位得到对应的x
位,与原来的权限进行或运算,设置结果作为新的权限)。以下所有解决方案均假设处理文件
“$FILE”
。解决方案 1 –
如果
将当前权限的模式作为文本这可能是最直接的方法:
解决方案 2 – 使用
find
,利用-perm
和-exec
选项这种方法使用
find
不是查找多个文件,而是查找多个文件要么找到给定的文件(如果它具有一定的权限),要么不找到查找任何内容(否则),并在找到文件时设置匹配的所需权限(否则不执行任何操作):这三种情况可以轻松组合成一个
for
循环:解决方案3(仅限
zsh
) – 使用 glob 限定符此方法仅在
"$FILE"
上运行每个相关的chmod
命令如果它已经匹配相应的权限。注意<代码>||添加 : 是为了避免在没有匹配项时出现错误,即文件没有相应的权限(另请注意zsh
仍然会发出no matches find
在这种情况下发出警告):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 ther
bits, shifting right 2 bits to get the correspondingx
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 –
if
ing on the pattern of the current permissions as textThis is perhaps the most straightforward approach:
Solution 2 – using
find
, taking advantage of the-perm
and-exec
optionsThis 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):The three cases can easily be combined into a single
for
loop:Solution 3 (
zsh
only) – using glob qualifiersThis 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 notezsh
still emits ano matches found
warning in this case):这可能不是最有效的方法,但我真的很喜欢
find
命令的直观 API。以下命令查找当前目录(.)中该组或所有用户可读的所有文件和目录:
并且此命令查找所有者可读但该组或所有用户不可读的所有文件和目录用户:
找到要处理的文件后,您可以添加
-exec
参数来对每个匹配项执行命令。例如,以下命令将在仅所有者可读的所有文件和目录上设置所有者的可执行位:
该行的结尾很奇怪,但完全按照所示输入它,它应该可以工作。
此命令将为组和其他人可读的所有文件和目录设置“组”和“其他”的可执行位:
所有这些命令都在当前目录中递归搜索。您可以通过将
.
替换为另一个路径来指定任意其他目录。您还可以使用
-maxdepth N
指定搜索的深度。编辑:
如果您想处理单个指定文件,可以使用以下脚本。它使用
stat
命令检查文件的权限,该命令以类似于ls -l
显示的格式返回权限,例如-rw-r--r- -
。该脚本适用于 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:
And this command finds all files and directories that are readable by the owner but NOT readable by the group or by all users:
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:
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:
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 whatls -l
displays, for example-rw-r--r--
.This script works in bash and zsh.