【问题标题】:Perform command multiple times using output in terminal使用终端中的输出多次执行命令
【发布时间】:2017-06-16 22:51:48
【问题描述】:

我正在尝试执行以下操作:

mdfind -name "application name"

作为输出我得到:

/Applications/[Application]
~/Library/LaunchAgents/[Application]
...

我想做的下一步是:

sudo rm -rif "/Applications/[Application]"
sudo rm -rif "~/Library/LaunchAgents/[Application]"
...

所以在这种情况下,我必须多次执行sudo rm -rif "/..."。如何自动为所有给定目录重复应用此删除命令?

P.S. 将输出划分为字符串数组并启动 for 循环不是一种选择。

【问题讨论】:

  • 请添加您要提示一次向用户呈现所有个删除候选的要求,然后批量 - 删除,直接到你的问题。如果这不是您想要的,请澄清 - 直接在您的问题中
  • 小心。 sudo rm -rif "~/Library/LaunchAgents/[Application]" 不会将 ~ 解释为您的主目录。
  • @thatotherguy:这是一个很好的观点。幸运的是,尽管有 OP 的示例代码,mdfind 始终输出绝对文字路径,而不是基于~ 的路径。
  • sudo rm -rif ~/"..." 会按预期运行;通过不引用它,shell 在将生成的路径传递给 sudo 之前扩展波浪号。

标签: bash macos terminal delete-file


【解决方案1】:

我们现在知道,在执行实际删除之前,您首先要向用户显示 mdfind 输出以供确认。

Barmar's answer 可以帮助您完成大部分工作,但是 - 在撰写本文时 - 执行实际删除的方式既脆弱又低效。[1]

这是一个可靠的替代方案,它只做了一个假设:没有路径嵌入换行符(这非常罕见)。

#!/bin/bash

# Determine the paths of the items to delete.
files=$(mdfind -name "application name")

# Present the paths to the user and ask for confirmation.
printf '%s\n' "$files"
read -p "OK to delete (y/N)? "
[[ $REPLY == [yY] ]] || { echo "Aborted." >&2; exit 2; }

# Perform batch deletion, passing (typically) *all* paths to `sudo rm -rf` *at once*.
printf '%s\n' "$files" | tr '\n' '\0' | xargs -0 sudo rm -rf

请注意,如果在删除之前不需要显示路径,您可以使用mdfind -0 -name "application name" 生成NUL-分隔的输出直接传递给xargs -0

由于 shell 变量不能包含嵌入的NULs,因此首先生成\n-分隔的输出,用于显示,然后再转换为NUL-分隔的输出,使用tr,用于xargs -0

始终使用NUL-separated 输出是最可靠的选项,因为这样即使是带有嵌入换行符的路径也能正确处理。

在手头的情况下,这需要首先将mdfind 输出缓存到一个临时文件中,鉴于嵌入换行符的文件名是极为罕见。


[1] 以下几点解决了边缘情况,但重要的是要知道它们可能是个问题:
* read 没有 -r 选项会使输入接受 \ 字符的解释。
* read 不将 IFS 设置为空字符串 (IFS= read ...) 会修剪前导和尾随空格。
为每个文件名调用一次rm 的效率低于传递所有文件名一次

【讨论】:

    【解决方案2】:

    将输出放入变量中,并显示给用户。然后将变量通过管道传递给执行命令的循环:

    files=$(mdfind -name "application name")
    echo "$files"
    read -p "OK to delete? " ok
    if [[ $ok =~ ^y ]]
    then 
        echo "$files" | while read -r filename; do
            sudo rm -rif "$filename"
        done
    fi
    

    【讨论】:

    • 首先我需要向用户显示所有找到的目录,然后才删除它们。并不总是可以重新执行 mdfind -name "application name",因为可能有很多文件
    • 我不明白这个问题。我已经更新了答案以显示如何首先显示结果,然后在循环中使用它们。
    猜你喜欢
    • 2015-03-26
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    • 2015-08-27
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多