最终剧本

最终剧本

我有一个充满文件的目录。我的目标是将文本附加到文件的开头。每个文件开头的文本都是相同的。这是我的尝试

#!/bin/bash                                                                                                                                                    

for file in `find . -type f -executable`;do                                                                                                                                 
    sed '/\#!/bin/bash\/a Hello Word'                                                                                                                                            


done

我的脚本除了崩溃什么也没做

答案1

#!/bin/bash

for file in `find . -type f -executable`;do
    sed '/\#!/bin/bash\/a Hello Word'
fi

done

这个脚本有很多问题。


首先,它不是有效的 Bash 脚本,因为您没有fi相应的if.


从风格上(删除该fi行后),我会删除前面的空行done并在 之前添加一个空格do。但这相对微不足道。


现在,就最佳实践而言,您使用反引号进行命令替换,而不是推荐的现代形式$(...).支持反引号纯粹是出于历史原因,不建议任何新脚本使用;看:


你有一个鲁棒性问题,因为你正在循环输出find——这是一个非常糟糕的主意,而且完全没有必要。您的脚本将在任何包含空格或特殊字符的文件名上中断。看:


如果您希望脚本可移植,则应尽可能坚持 POSIX 指定的功能。特别是-executable主要的findPOSIX 未指定。考虑使用-perm +700代替。

同样在可移植性领域,在 GNU Sed 中使用a不带以下\<newline>序​​列的 Sed ( ) 的“append”命令可以工作,但不是标准的。


您依次将循环file中的变量设置for为每个文件的名称(假设文件名中没有特殊字符或空格,这将导致变量file包含以下内容)不是一个文件名),但你实际上从未使用变量file

您的 Sed 命令没有提供任何要运行的文件,因此它将尝试在标准输入上运行。因此,当您运行脚本时,它只会等待输入。


您的 Sed 脚本本身不正确,与它缺少要操作的文件名这一事实无关。

如果您用作/正则表达式的分隔符(这是最常见的),则需要反斜杠转义/正则表达式中出现的所有实例。命令中唯一将被读取为正则表达式的部分是/\#!/,其余部分(以 开头bin)将被解释为 Sed 命令。

相反,通常的解决方案是替换每个/ 其他比最终的正则表达式分隔符\/. (我看到你逃脱了仅有的最后一个斜杠,应该不是被逃脱。)

有一个Sed 中鲜为人知的功能,您可以在这里利用它来发挥您的优势。 任何字符(反斜杠或换行符除外)可以用作正则表达式分隔符,而不仅仅是使用斜杠。因此,您可以使用等效的地址,而不是用作/#!\/bin\/bash/Sed 地址\:#!/bin/bash:


现在,如果您已经处理了上述所有问题,您将拥有一个可以工作的脚本。它可能不会做你想做的事它要做,但实际上会做一点事。这样的脚本看起来像这样:

#!/bin/bash

find . -type f -perm -700 -exec sed '\:#!/bin/bash:a\
Hello World' {} +

这个脚本有什么作用?它递归地搜索当前目录以查找设置了可执行位(所有者)的所有文件,并且对于每个此类文件,打印整个文件,并Hello World在包含文本的任何行之后附加文本#!/bin/bash

sed 实际上不是设计的用于就地编辑文件;它是流编辑器。 GNU Sed 将允许您使用开关就地编辑文件-i,但我只会使用标准工具ex用于文件编辑。


但这里还有一点。如果您想Hello World在 Bash 脚本中添加该行,它实际上不会执行任何操作,因为Hello它不是有效的命令名称。也许你想要的是打印Bash 脚本中的文本“Hello World”,换句话说,添加echo "Hello World,这可能是有意义的。

现在我们要更准确地阐明您的脚本是什么应该去做。


最终剧本

所以我对该脚本的规范的更准确的说明是:

  • 该脚本应查找当前目录(或递归的任何子目录)中为所有者设置了可执行位的所有常规文件。
  • 对于每个这样的文件,脚本应检查文件的第一行是否完全等于字符串#!/bin/bash
  • 仅对于具有该精确第一行的文件,脚本应echo "Hello World"在文件的第一行之后插入精确的 text ,后跟换行符。 (此更改应保存到文件中,而不是打印到标准输出。)

下面是一个符合这些确切规范的脚本,仅使用 POSIX 工具和功能:

#!/bin/sh

find . -type f -perm -700 -exec sh -c '
  for f
  do
    head -n 1 "$f" | grep -qFx "#!/bin/bash" &&
      printf "%s\n" "1a" "echo \"Hello World\"" . x | ex "$f"
  done
' find-sh {} +

答案2

你想实现什么目标?要查找可执行脚本,请使用以下命令

find . -type f -perm /u+x,g+x,o+x | while read file
do
    filename=$(echo ${file} | awk -F/ '{print $NF}')
    echo "File Name : ${filename}"
done

如果您尝试在 shebang 行之后附加 Hello World,那么您的 sed 命令应该是

 sed '/\#!/bin/bash/a Hello Word' ${file}

如果您想对文件本身进行更改,请在 sed 命令中添加 -i

答案3

find . -type f -executable -exec sed '/^#!\/bin\/bash/a Hello World' {} \;

相关内容