使用 Zsh 循环 grep 结果

发布于 2025-01-10 09:50:39 字数 346 浏览 0 评论 0原文

第一次登录新虚拟机并设置 WSL 共享文件夹的权限时,我需要循环访问目录。除非设置了 0700 权限,否则 SSH 代理不会添加私钥。

如何使用 grep 获取文件名列表,然后循环遍历它们?

我尝试过:

for file $(grep -lr "-----BEGIN OPENSSH PRIVATE KEY-----")
  do
    echo "Working on File: $file"
    chmod 700 $file
  done

结果一团糟。 grep 命令被解析为单个文件名字符串。任何包含空格的映射目录(来自房子的 Win11 一侧)都会使事情变得更加混乱。

I need to loop through a directory the first time I log into a new VM and set permissions on WSL shared folders. The SSH agent will not add private keys unless they have 0700 permissions set.

How do I use grep to get a list of file names and then loop through them?

I tried:

for file $(grep -lr "-----BEGIN OPENSSH PRIVATE KEY-----")
  do
    echo "Working on File: $file"
    chmod 700 $file
  done

The results were a mess. The grep command is being resolved into a single string of file names. Any mapped directories that have spaces in them (from the Win11 side of the house) messed things up further.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

以酷 2025-01-17 09:50:39

建议用一行完成任务:

chmod -v 700 $(grep -lr "-----BEGIN OPENSSH PRIVATE KEY-----" $PWD)

说明:

-v:打印每个更改文件的详细报告。

grep -lr "-----BEGIN OPENSSH PRIVATE KEY-----" $PWD :列出当前目录下所有文件中所有匹配的要更改的文件。

注意:还尝试将 $PWD 替换为 $HOME

Suggesting to accomplish the task in one line:

chmod -v 700 $(grep -lr "-----BEGIN OPENSSH PRIVATE KEY-----" $PWD)

Explanation:

-v: Print verbose report on each changed file.

grep -lr "-----BEGIN OPENSSH PRIVATE KEY-----" $PWD : List all matched files to be changed, from all files under current directory.

Note: also try to replace $PWD with $HOME.

笑饮青盏花 2025-01-17 09:50:39

这是我的解决方案:

  1. grep 将输出带有“-Z”标志的每个项目后带有空字符的文件名。
  2. Zsh 可以采用该空分隔符,并在带有“0”标志的扩展字符串中使用它。

最终结果:

    for file in ${(0o)"$(grep -lrZ "-----BEGIN OPENSSH PRIVATE KEY-----" *)"} 
        do
            echo "Working on $file"
            chmod 700 $file
        done

后人详细解释:

  • Zsh 将在子 shell 中执行 () 内的任何内容。所以 grep 的结果在一个无名变量 $() 中。

  • Zsh 使用 ${} 进行变量/参数扩展。里面的任何内容都会被展开,就像在命令提示符下按“Tab”一样。

  • 我们知道 grep 将返回其中包含空格的文件路径。因此我们不能使用空格来扩展文件列表。我们可以使用标志来实现 grep 和 Zsh 使用空字符作为分隔符而不是空格。

  • Zsh 标志在大括号打开后立即指定。

    • ${(0o)$foo} 将导致 $foo 扩展为一个项目数组,由于“0”而将 $foo 拆分为空值,并由于“o”标志而按升序对它们进行排序。< /里>
    • 我们需要额外的步骤,将 grep 结果括在双引号中。 ${(0o)"$foo"} 我们正在寻找一个同时包含空格和空值的字符串。我们将根据空值分割字符串并保留路径名中的空格。
    • 如果您想这样做,可以使用大写“O”按降序对它们进行排序。
  • grep -lrZ 将在使用 * 通配符找到的所有文件中查找字符串“-----BEGIN OPENSSH PRIVATE KEY-----”。

    • “r”在子目录中递归查找
    • -l 仅输出文件名
    • 并且 -Z 在每个结果的末尾输出一个空分隔符。

因此,您最终会使用 grep 查找文件,Zsh 扩展列表,然后循环遍历返回数组中的每个项目。

作为 WSL 中的旁注,您必须打开元数据才能挂载 Windows 文件夹并设置 Linux 权限。这是一个很好的解决方案,可以将 ssh 密钥保存在安全的备份位置并在 Linux 映像上使用它们。

Here is my solution:

  1. grep will output filenames with a null character after each item with the "-Z" flag.
  2. Zsh can take that null delimiter and use it in an expanded string with the "0" flag.

The final result:

    for file in ${(0o)"$(grep -lrZ "-----BEGIN OPENSSH PRIVATE KEY-----" *)"} 
        do
            echo "Working on $file"
            chmod 700 $file
        done

A detailed explanation for posterity:

  • Zsh will execute anything inside () in a subshell. so the results of grep are in a nameless variable $().

  • Zsh does variable/parameter expansion with ${}. Anything inside gets expanded like hitting "Tab" at the command prompt.

  • We know that grep is going to return file paths with spaces in them. Therefore we can't use whitespace to expand our file list. We can use flags to make it happen with grep and Zsh using null characters as delimiters instead of spaces.

  • Zsh flags are specified immediately after the curly braces are opened up.

    • ${(0o)$foo} will result in $foo being expanded into an array of items, splitting $foo on nulls because of the "0" and sorting them in ascending order because of the "o" flag.
    • We need the extra step of enclosing our grep results in double-quotes. ${(0o)"$foo"} We are after a string that contains both spaces and nulls. We are going to split the string on the nulls and preserve the spaces in the path names.
    • You could sort them in descending order with a capitalized "O" if you wanted to do it that way instead.
  • grep -lrZ will look for the string "-----BEGIN OPENSSH PRIVATE KEY-----" in all files found with the * wildcard.

    • The "r" is recursively look in sub-directories
    • The -l outputs just the filename
    • And -Z outputs a null separator at the end of each result.

So you end up with grep finding the files, Zsh expands the list and then loops through each of the items in the returned array.

As a side note in WSL, you have to turn on metadata in order to mount a windows folder and set Linux permissions. It is a nice solution to keep your ssh keys in a secure, backed-up location and use them on Linux images.

谎言 2025-01-17 09:50:39

迭代所有文件,但仅对grep成功的文件进行操作。 (您可能没有那么多文件;不必太担心 grep 必须运行多少次。)

for f in *; do
    if grep -q "-----BEGIN OPENSSH PRIVATE KEY-----" "$f"; then
        echo "Working on File: $f"
        chmod 700 $f
    fi
done

并且因为这是 zsh,所以您可以嵌入在 glob 中调用 grep

is_key () {
    grep -q "-----BEGIN OPENSSH PRIVATE KEY-----" "$REPLY"
}
for f in *(+is_key); do
    echo "Working on File: $f"
    chmod 700 "$f"
done

或者甚至省去显式循环

chmod 700 *(+is_key)

(shell 函数实际上并不是必需的,但它确实有助于提高 glob 限定符的可读性。)

Iterate over all the files, but only operate on the ones that grep succeeds on. (You probably don't have that many files; don't worry so much over how many times grep has to run.)

for f in *; do
    if grep -q "-----BEGIN OPENSSH PRIVATE KEY-----" "$f"; then
        echo "Working on File: $f"
        chmod 700 $f
    fi
done

And because this is zsh, you can embed the call to grep in the glob:

is_key () {
    grep -q "-----BEGIN OPENSSH PRIVATE KEY-----" "$REPLY"
}
for f in *(+is_key); do
    echo "Working on File: $f"
    chmod 700 "$f"
done

or even dispense with the explicit loop

chmod 700 *(+is_key)

(The shell function isn't actually necessary, but it does help with the readability of the glob qualifier.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文