【问题标题】:How can I filter nonexistent files when piping through xargs realpath?通过 xargs realpath 管道时如何过滤不存在​​的文件?
【发布时间】:2020-03-04 04:06:33
【问题描述】:

我已经养成了使用以下命令在我的编辑器中快速打开相关文件进行代码审查的习惯。

git diff --name-only master... | xargs realpath | someEditor

但最近遇到一个问题,第一个或第二个文件可能已被删除,编辑器会产生错误消息,并且无法打开其余文件,迫使我一个一个打开它们。

我可以键入类似的命令来跳过不存在的文件吗?

【问题讨论】:

  • 根据该命令的手册页,“除了最后一个组件之外的所有组件都必须存在”。
  • 使用readlink,它有关于如何处理不存在的文件的明确选项。
  • @CharlesDuffy readlink 似乎没有输出任何内容。也是的,我得到了绝对路径位,但我猜我习惯了路径必须存在的 php realpath。
  • readlink 有选项(-f-m 等)。选择哪一个对于选择其行为很重要。
  • 顺便说一句,请注意 xargs 在名称中包含空格时是不可靠的,除非您使用 -0(带有 NUL 分隔的输入和输出)或 -d $'\n'(带有换行符分隔的输入和输出,但需要 GNU 工具)。

标签: bash ubuntu realpath


【解决方案1】:

狭隘地解决问题:使用 Readlink

由于您使用的是 Ubuntu(具有 GNU 读取链接),因此您可以使用 readlink -e,它具有您希望realpath 将提供的确切行为:

git diff --name-only master... \
  | xargs -d $'\n' readlink -e -- \
  | xargs -d $'\n' someEditor

由于您使用的是提供 GNU xargs 的 Ubuntu,因此由于在两个 xargs 调用中都使用了 -d $'\n',此代码将正确处理带有空格、文字引号或文字反斜杠的文件名。


狭隘地解决问题:使用 Realpath

如果我们想坚持使用您现有的工具(也就是说,realpath 而不是 readlink)并添加一个存在测试,可能如下所示:

git diff --name-only master... \
  | xargs -d $'\n' sh -c 'for f; do [ -e "$f" ] && realpath "$f"; done' _ \
  | xargs -d $'\n' someEditor

实施建议

顺便说一句——考虑将你想要的实现封装在你的~/.bashrc 中的一个shell 函数中。这可能是……

forEachChangedFile {
  local -a files
  readarray -t files < <(
    git diff --name-only "${branchExpr:-master...}" \
      | xargs -d $'\n' readlink -e --
  )
  if (( $# )); then
    "$@" "${files[@]}"
  else
    "${EDITOR:-someEditor}" "${files[@]}"
  fi
}

...后来用作:

forEachChangedClient vim

branchExpr=someBranch..someOtherBranch forEachChangedFile emacs-client

在编辑器的最终调用中不使用xargs 的好处是它使编辑器的标准输入保持清晰,因此您可以将它用于通过该通道与用户通信的编辑器。

【讨论】:

  • 感谢您的见解。我希望有一些不那么复杂的方式,我可以在不编写脚本的情况下直接打字。但是为 macOS 和 Ubuntu 制作一个跨平台脚本可能是最好的,我会使用你的部分答案,所以标记为最佳答案。
猜你喜欢
  • 1970-01-01
  • 2011-04-06
  • 1970-01-01
  • 1970-01-01
  • 2017-10-04
  • 2023-04-07
  • 1970-01-01
  • 2021-01-06
  • 2016-06-14
相关资源
最近更新 更多