如何使除少数文件类型之外的所有文件都可执行?

如何使除少数文件类型之外的所有文件都可执行?

我有一个文件夹,其中包含许多 C 源文件和相同数量的编译输出文件。

我为所有这些文件设置了可执行位,但由于某种原因它丢失了,使它们不可执行。(我认为这是因为我将该文件夹移动到 NTFS 分区一段时间)

我想让它们(但不是我目录中的其他文件)再次可执行。一种可能的方法是将所有源文件从该文件夹移动到临时文件夹并执行以下操作:

chmod +x *

然后将源文件移回当前文件夹。

是否可以在不移动文件的情况下执行相同的操作?

笔记:

编译的输出文件没有扩展名(在C中)

答案1

这取决于您如何定义哪些文件应设置为可执行文件。例如,如果考虑文件名中没有点的所有文件,您可以使用:

find -type f -not -name "*.*" -exec chmod +x \{\} \;

这将递归地找到文件名中没有点的所有文件(不是目录)并将它们设置为可执行文件。如果您想将其限制为仅当前目录,请添加-maxdepth 1参数,如下所示:

find -maxdepth 1 -type f -not -name "*.*" -exec chmod +x \{\} \;

您还可以依靠file命令来告诉您文件是否是 ELF 可执行文件。为此,您可以运行如下命令:

find -type f -exec /bin/sh -c "file {} | grep -q executable && chmod +x {}" \;

这将递归地查找所有常规文件并对file它们调用命令。然后,grep 将在此命令的输出中查找“可执行”字符串(应该类似于ELF 32-bit LSB executable ...),并且仅当找到它时,chmod才会在此文件上调用。

当然,你也可以-maxdepth 1在这种情况下添加禁用递归搜索。

答案2

你可以这样做:

find /pathtostuff -type f ! -name "*.c" -exec chmod +x {} +

这会查找/pathtostuff以下文件缺少扩展.c并为其添加执行权限。

更新

这也可以扩展到处理其他 C 扩展:

find . -type f ! -name "*.c" ! -name "*.h" ! -name "*.cc" ! -name "*.cpp" -exec chmod +x {} +

另类方法

该脚本与扩展无关。它查找“二进制”文件而不是“文本”文件。

#!/usr/bin/env perl
use strict;
use warnings;
use File::Find;
my @dir = @ARGV ? @ARGV : ('.');
my @files;
find( sub { -f $_ && !-T $_ && push @files, $File::Find::name }, @dir );
for my $file (@files) {
    system("echo  +x $file");
}

只需传递要检查的目录路径即可。运行不带任何参数的脚本来处理当前工作目录。

答案3

在 zsh 中:

setopt extendedglob
chmod +x -- ^*.c

使用 ksh,或带extglob选项的 bash,或带选项的 zsh kshglob

chmod +x -- !(*.c)

使用ksh93(不过最好避免使用FIGNORE):

FIGNORE='@(.*|*.c)'
chmod +x -- *

对于所有内容,替换*.c*.*以排除任何带点的内容。

使用 zsh,您可以使用全局限定符做一些好事,例如:

oftype() [[ $(file -b --mime-type -- $REPLY) = $type ]]
type=application/x-executable; chmod +x -- **/*(.+oftype)

这将匹配常规文件“oftype” application/x-executable(递归下降到子目录)。

答案4

这也可能有效

chmod +x $(find . -type f -print0 | xargs -0 file | grep "ELF [^,;]* executable" |  cut -d: -f1)

如果您的文件名称中包含空格、制表符、换行符、星号、问号、尖括号或反斜杠字符,或者它们太多而无法放入一个命令行,您仍然会遇到问题。

相关内容