所以我是一个初学者,我下周有一个项目要到期。我必须仅打印#!/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
)。