在第一行中搜索模式后仅打印文件名(使用 grep 和 head)

在第一行中搜索模式后仅打印文件名(使用 grep 和 head)

所以我是一个初学者,我下周有一个项目要到期。我必须仅打印#!/bin/bash第一行包含的文件的文件名。到目前为止我尝试过这个

head -n 1 $filename | grep -l "pattern"

但是当我执行它而不是我收到的文件的名称时

(standard input)

就像我说的,我是初学者,到目前为止我熟悉简单的命令。所以我想知道我在哪里搞砸了,是否有一种方法可以实现我想要的而不使用像awk.

for fis in  find -perm -a+x -name "*.sh" -type f
do
head -n 1 $fis | grep -l "#!/bin/bash"
done

答案1

在 GNU 中,如果输入来自 stdin,则grep可以使用选项来设置标签/文件名。--label

-exec您可以使用该操作来启动一个小脚本来循环文件名并执行命令,而不是使用带有命令替换的外部循环。

find -perm -a+x -name "*.sh" -type f -exec sh -c '
  for fis; do
    head -n1 "$fis" | grep --label="$fis" -Fl "#!/bin/bash"
  done
' sh {} +

我添加了该-F选项,grep因为我们正在寻找固定字符串。

答案2

我知道您已将 awk 列入黑名单,但对于其他遇到您的问题寻求帮助的人来说,这是打印第一行中.sh包含的可执行文件的名称的一种非常有效的方法:#!/bin/bash

find . -perm -a+x -name '*.sh' -type f -exec \
    awk 'NR == 1{ if ($0 == "#!/bin/bash") print FILENAME; exit }' {} \;

#!/bin/bash或者,要打印第一行中的文件名而不受进一步限制,请删除-perm-name选项:

find . -type f -exec awk ...

答案3

find . -perm -a+x -name '*.sh' -type f |
    while IFS= read -r file; do
        test -f "$file" || continue
        if head -n 1 "$file" | grep -qFx '#!/bin/bash'; then
            echo "$file"
        fi
    done

答案4

我意识到这对聚会来说已经很晚了,但我一直在做完全相同的事情,并且取得了很好的结果:

find . -perm -a+x -name "*.sh" -exec \
    bash -c 'grep -q "pattern" < <(head -n 1 "$1")' _ {} \; -printf '%p\n'

据了解,该-q标志可防止写入标准输出,从而允许您打印文件名(%p来自find -printf)。

相关内容