删除文件名但保留 grep 结果的路径

Remove filename but keep the path from grep result

我得到了包含我的握力结果的文件列表。

$ grep -il 'name:red' */*/doc.txt
current_dir/Big_A/Folder1/doc.txt
current_dir/Big_A/Folder2/doc.txt
current_dir/Big_C/Folder5/doc.txt

我现在想将与我的结果匹配的整个文件夹移动到其他地方,并根据其 doc 文件中的内容重命名。虽然我已经成功地用

找到了我想要的名字
$ grep -i 'name:red' */*/doc.txt | cut -f2- -d:
Red Bucket
Red Asparagus
Red Blueberries

我在删除最后一个文件名时画了一个空白,这样我就可以移动整个文件夹。

我已经尝试使用 cut 对其进行一些管道处理,但找不到一种工作方法可以让我在正确的位置进行切割,因为 gitbash 不支持 rev 并且 cut --output-delimiter=doc 什么也没做。

编辑:发布 20 秒后我发现 sed 's/search/replace' 解决了前半部分。

这就是我想要的结果

current_dir/Mars/Red Bucket/doc.txt
current_dir/Mars/Red Asparagus/doc.txt
current_dir/Mars/Red Blueberries/doc.txt

这个确实不太清楚。但也许是这样的?

#!/bin/Bash
grep -il 'name:red' */*/doc.txt |
while IFS='' read -r matched; do
    folder=${matched%/*}
    newdest=$(grep -i -m1 'name:red' "$matched")
    echo mv ./"$folder" current_dir/Mars/"$newdest"
done

如果这看起来像您想要的,请删除 echo 使其成为实际 运行 mv.

cut 对字符串不起作用的原因是它只允许使用单字符定界符。在这里,我们使用 shell 内置的 parameter expansion 工具来 trim 文件名的后缀。

我们使用 grep -m 1 只打印每个文件中的第一个匹配项。如果您知道每个文件中只能有一个匹配项,则可以将其删除。如果您可以指定一个更受约束的正则表达式以确保您只获得一个匹配项,则可以使用 sed 或 Awk 而不是 grep 从较长的模式匹配中获取有趣的部分。例如,

    newdest=$(sed -n 's%.*<tag attrib="name:red">\([^<>]*\)</tag>.*%%p' "$matched")

从类似 XML 的标签结构中提取有趣的字符串。 (尽管使用面向行的正则表达式工具处理 XML 既脆弱又复杂;如果您的输入确实是 XML,也许可以为此使用适当的 XML 解析器。)