【问题标题】:How can I use aliased commands with xargs?如何在 xargs 中使用别名命令?
【发布时间】:2010-11-02 01:00:18
【问题描述】:

我的 .aliases 中有以下别名:

alias gi grep -i

我想在名称中包含字符串bar 的所有文件中不区分大小写地查找foo

find -name \*bar\* | xargs gi foo

这是我得到的:

xargs: gi: No such file or directory

有没有办法在 xargs 中使用别名,还是必须使用完整版:

   find -name \*bar\* | xargs grep -i foo

注意:这是一个简单的例子。除了gi,我还有一些非常复杂的别名,我无法轻易手动扩展。

编辑:我使用了tcsh,所以请说明答案是否是特定于外壳的。

【问题讨论】:

标签: linux tcsh xargs


【解决方案1】:

别名是特定于 shell 的——在这种情况下,很可能是特定于 bash 的。要执行别名,您需要执行 bash,但别名仅为交互式 shell 加载(更准确地说,.bashrc 只会在交互式 shell 中读取)。

bash -i 运行交互式 shell(和源 .bashrc)。 bash -c cmd 运行 cmd

把它们放在一起: bash -ic cmd 在交互式 shell 中运行 cmd,其中 cmd 可以是定义在你的.bashrc

find -name \*bar\* | xargs bash -ic gi foo

应该做你想做的。

编辑:我看到您已将问题标记为“tcsh”,因此特定于 bash 的解决方案不适用。使用 tcsh,您不需要 -i,因为它似乎读取 .tcshrc,除非您提供 -f

试试这个:

find -name \*bar\* | xargs tcsh -c gi foo

它适用于我的基本测试。

【讨论】:

  • 如果您想在包含空格的文件中表现得很好,请参阅this answer
【解决方案2】:

将“gi”改为脚本

例如,/home/$USER/bin/gi:

#!/bin/sh
exec /bin/grep -i "$@"

不要忘记将文件标记为可执行文件。

【讨论】:

    【解决方案3】:

    建议here 是避免使用xargs 并使用“while read”循环而不是xargs:

    find -name \*bar\* | while read file; do gi foo "$file"; done
    

    有关处理文件名中的空格或换行符的改进,请参阅上面链接中接受的答案。

    【讨论】:

    • 如果文件名中有空格或换行符,这不如带有-0选项的xargs(并使用-print0查找)。
    【解决方案4】:

    这个解决方案在 bash 中非常适合我:
    https://unix.stackexchange.com/a/244516/365245

    问题

    [~]: alias grep='grep -i'
    [~]: find -maxdepth 1 -name ".bashrc" | xargs grep name      # grep alias not expanded
    [~]: ### no matches found ###
    

    解决方案

    [~]: alias xargs='xargs ' # create an xargs alias with trailing space
    [~]: find -maxdepth 1 -name ".bashrc" | xargs grep name     # grep alias gets expanded
    # Name     : .bashrc
    

    为什么会起作用

    [~]: man alias  
    alias: alias [-p] [name[=value] ... ]  
    (snip)  
    A trailing space in VALUE causes the next word to be checked for
    alias substitution when the alias is expanded.
    

    【讨论】:

    • 如果我们使用 find -print0 | 它不起作用xargs -0 grep
    【解决方案5】:

    这是特殊字符安全的:

    find . -print0 | xargs -0 bash -ic 'gi foo "$@"' --
    

    -print0-0 使用以\0NUL 结尾的字符串,这样当文件名中有空格时,您就不会发生奇怪的事情。

    bash 将命令字符串后面的第一个参数设置为$0,因此我们将其传递给一个虚拟参数(--),这样find 列出的第一个文件就不会被$0 使用.

    【讨论】:

      【解决方案6】:

      对于 tcsh(没有函数),你可以使用:

      gi foo `find -name "*bar*"`
      

      对于 bash/ksh/sh,您可以在 shell 中创建一个函数。

         function foobar 
         {
            gi $1 `find . -type f -name "*"$2"*"`
         }
      
         foobar foo bar
      

      请记住,从多个角度来看,在 shell 中使用反引号比使用 xargs 更有优势。将函数放在您的 .bashrc 中。

      【讨论】:

        【解决方案7】:

        使用 Bash,您还可以指定传递给别名(或函数)的参数数量,如下所示:

        alias myFuncOrAlias='echo'  # alias defined in your ~/.bashrc, ~/.profile, ...
        echo arg1 arg2 | xargs -n 1 bash -cil 'myFuncOrAlias "$1"' arg0
        

        (应该以类似的方式为 tcsh 工作)

        # alias definition in ~/.tcshrc
        echo arg1 arg2 | xargs -n 1 tcsh -cim 'myFuncOrAlias "$1"' arg0  # untested
        

        【讨论】:

          【解决方案8】:

          在您的情况下,最简单的解决方案是扩展您的内联别名。但这仅对 csh/tcsh 有效。

          find -name \*bar\* | xargs `alias gi` foo
          

          对于 bash,它会更棘手,不是那么方便,但仍然可能有用:

          find -name \*bar\* | xargs `alias gi | cut -d "'" -f2` foo
          

          【讨论】:

            猜你喜欢
            • 2020-03-31
            • 2017-11-15
            • 2010-10-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-08-22
            • 1970-01-01
            相关资源
            最近更新 更多