为所有 bash 文件添加 .sh 扩展名

为所有 bash 文件添加 .sh 扩展名

我有一个包含多个文件的目录,其中一些文件是 bash 脚本,但它们的名称不包含 .sh 扩展名。我知道我需要使用 file 命令来了解带有 -type 选项的文件类型,我也知道我可以使用 xargs 重定向输出,这样我就可以使用原始名称 + .sh 扩展名重命名文件。问题是我不知道如何将所有命令连接在一起,也不知道如何查找仅 bash ASCII 文本可执行文件的文件类型。知道如何用一个简单的命令来做到这一点吗?

答案1

如果您设置了任何标准 shebang 行,它看起来file(至少版本 5.39)应该能够检测到它们:

$ echo '#!/usr/bin/env bash' > 1
$ echo '#!/bin/bash' > 2
$ echo '#!/usr/bin/bash' > 3
$ file *
1: Bourne-Again shell script, ASCII text executable
2: Bourne-Again shell script, ASCII text executable
3: Bourne-Again shell script, ASCII text executable

所以我们应该能够这样做:

for path in ./*
do
    if [[ "$(file "$path")" = "${path}: Bourne-Again shell script, ASCII text executable" ]]
    then
        mv "$path" "${path}.bash"
    fi
done

这适用于上面的示例文件(并且应该适用于不寻常的文件名,包括包含空格字符、以连字符开头或以换行符结尾的文件名):

$ ls
1.bash  2.bash  3.bash

这可能会不是如果您的文件没有 shebang 行(这对于以下文件是合理的),则可以工作由其他脚本获取或者 shebang 行是错误的(例如#!/bin/sh)。

(我使用了“.bash”,因为它比“.sh”更明确。)

答案2

尽管这不能完成您的作业,但不需要findas grepkann 递归地搜索文件目录-r(甚至当文件名通过通配符传递时也不需要)

grep -lIw '^#!.*bash' dir/!(*.sh) | xargs -I_ mv _ _.sh

grep-r 目录将搜索所有子目录中的所有文件(此处未使用)

grep-l类似于-H打印每个匹配的文件名,但抑制正常输出。此外,它在第一个匹配后停止,类似于-q-m1

grep-I排除二进制文件,仅处理文本文件

grep-w 巴什仅匹配整个单词(不匹配巴什编辑)


正则表达式^ #!仅匹配行首(不匹配 ##!

正则表达式.匹配任何字节*任何出现=.*任何字符串


路径名扩展(通配符)*.sh与模式 file.sh 匹配

扩展通配!(pattern)匹配除模式之外的任何内容

lsdir/!(*.sh)列出所有文件目录排除目录/文件.sh文件


参数-I 图案将在每个位置插入参数图案_本例中使用:

mv   _     _  .sh
mv file1 file1.sh
mv file2 file2.sh

相关内容