如何编辑名称包含空格的生成文件列表

如何编辑名称包含空格的生成文件列表

我有一个相对较小的文件名列表,这些文件名是从基于find.文件名包含空格和可能的标点符号,但绝对不包含其他非打印字符或换行符。

例如,

Netherlands/Purge (GDPR) 2020-01-09.txt
Netherlands/Purge (GDPR) 2020-01-27.txt
Switzerland/New mailing 2020-01-27.txt

我想将这些文件作为一组(vi file1 file2 file3而不是vi file1; vi file2; vi file3)进行编辑,部分原因是我可以轻松地在它们之间前后跳转。

我已经开始了使用生成的文件名列表作为参数列表 - 带空格 ,有一个标准find -print0 | xargs -0 mycommand解。不幸的是,当mycommand编辑者是编辑者时,这不起作用,因为尽管xargs可以组装要编辑的文件集,标准输入已从管道中占用,我看不到就地运行编辑器的方法。我无法使用,find -exec vi {} +因为我正在使用管道来验证文件名集,而不仅仅是find其本身。

我的另一个选择是复制和粘贴,组合文件名列表,用引号括起来,然后在结果前面加上vi.对于这三个文件来说,这很简单,但在一般情况下,它不是一个易于重用的解决方案,

vi 'Netherlands/Purge (GDPR) 2020-01-09.txt' 'Netherlands/Purge (GDPR) 2020-01-27.txt' 'Switzerland/New mailing 2020-01-27.txt'

给定一个 GNU/Linux 平台作为bash我的首选 shell(如果它很重要),我如何编辑类似生成的文件列表?

答案1

既然你在 Bash,

#!/bin/bash
readarray -d '' -t files < <(find path -type f -print0)
vi -- "${files[@]}"

替换find path -type f -print0为您的实际管道。

尽管您的文件没有换行符,但用户已添加对此类文件名的支持格伦·杰克曼

要使用制表符而不是缓冲区vi,请添加-p标志:vi -p ...


如果不需要管道,您可以直接使用该-exec选项:

find path -type f -exec vi -- {} +

答案2

不幸的是,当 mycommand 是编辑器时,这不起作用,因为尽管 xargs 可以组装要编辑的文件集,但 stdin 已经从管道中占用,并且我看不到就地运行编辑器的方法。

这种方式记录在 GNU Findutils 的手册页中xargs

   -o, --open-tty
          Reopen stdin as /dev/tty in the child process  before  executing
          the  command.  This is useful if you want xargs to run an inter‐
          active application.

这样你就可以使用

find . -name 'pattern' -print0 | xargs -0o vim

然而,这是一个较新的功能。我在具有 xargs 4.4.2 的旧系统中看不到它;我在 Ubuntu 18 上看到它,它有 xargs 4.7.0。

现在xargs可能没有-o十年前的选项,但 Bash 进程替代十年前就存在,并且xargs可以-a选择从文件读取而不是标准输入。

所以这个问题是可以解决的,不需要xargs -o这样:

xargs -0 -a <(find . -name 'pattern' -print0) vim

因为xargs正在读取(它认为是)作为参数接收的文件,所以它保留了标准输入。

答案3

从评论中我得到类似的东西,这是你的命令:

find -type f -mtime +14 -mtime -22 -iname '*.xml' | while IFS= read -f x; do xmlstarlet sel -T -t -v '//magicElement' -n "$x" | grep -q magicValue && echo "$x"; done 

while您可以使用管道-exec sh -c '...'来过滤文件,而不是通过管道连接到- 循环:

find -type f -mtime +14 -mtime -22 -iname '*.xml' \
  -exec sh -c 'xmlstarlet sel -T -t -v "//magicElement" "$1" | grep -q magicValue' find-sh {} \; \
  -exec vi -- {} +

尝试:

考虑三个文件:

.
├── a:<magicElement>magicValue</magicElement>
├── b:<magicElement>magicValue</magicElement>
└── c:<magicElement>someOtherValue</magicElement>

$ find . -type f \
  -exec sh -c 'xmlstarlet sel -T -t -v "//magicElement" "$1" | grep -q magicValue' find-sh {} \; \
  -exec echo vi -- {} +

输出:

vi -- ./a ./b

答案4

这是我多年来针对这个问题使用的两个丑陋的技巧。两者都需要 X。

find ... -print0| ...| xargs -0r gvim -f

find ... -print0| ...| xargs -0r xterm -e vim

即使通过 ssh,它也能工作。

相关内容