【问题标题】:xargs argument not interpretedxargs 参数未解释
【发布时间】:2021-02-01 21:04:25
【问题描述】:

我有一个目录$dir,其中包含.txt.xy 文件和带有.txt.xy 文件的子目录。我尝试遍历每个文件并将整个路径以及没有$dir 的路径作为参数传递给这样的程序:

dir="/path/to/"
suffix=".xy"

find "$dir" -name "*.txt.xy" -print0 | xargs -0 -I {} sh -c 'program "$1" |
  subprogram filename="$2"' _ {} "$(echo {} | sed -e "s#^${dir}##" -e "s#${suffix}\$##")"
  • $1 应该是完整路径(例如 /path/to/subdir/file.txt.xy
  • $2 应该是没有$dir$suffix 的完整路径(例如subdir/file.txt

$1 是正确的完整路径,但 $2 也是完整路径,就好像 $(...) 中的管道永远不会执行一样。我在这里错过了什么?

【问题讨论】:

    标签: shell sed xargs


    【解决方案1】:

    您的尝试似乎相当迂回。听起来你正在寻找

    find /path/to -name "*.txt.xy" -exec sh -c '
        for f; do
            g=${f##*/}
            program "$f" | subprogram filename="${g%.xy}"
        done' _ {} +
    

    如果您确实需要将参数放在变量中,则可以将后缀作为$0 传递,无论如何这里都不会用于任何有用的东西。它有点晦涩,但有助于避免双引号造成的混乱。

    find /path/to -name "*.txt.xy" -exec sh -c '
        for f; do
            g=${f##*/}
            program "$f" | subprogram filename="${g%"$0"}"
        done' ".xy" {} +
    

    上面的内容只是将g 修剪为基本名称,我猜想仔细阅读你不想要的。所以将/path/to 传递给$0,然后在里面硬编码.xy:

    find /path/to -name "*.txt.xy" -exec sh -c '
        for f; do
            g=${f#"$0"/}
            program "$f" | subprogram filename="${g%.xy}"
        done' "/path/to" {} +
    

    或者如果你真的需要两者都是命令行参数,

    dir="/path/to"
    suffix=".xy"
    find "$dir" -name "*.txt$suffix" -exec sh -c '
        suffix=$1
        shift
        for f; do
            g=${f#"$0"/}
            program "$f" | subprogram filename="${g%"$suffix"}"
        done' "$dir" "$suffix" {} +
    

    【讨论】:

    • 这是一个很好的方法,但值得考虑将所有这些逻辑从命令行中取出并将其放入脚本中。更容易理解find ... -exec script {} \;
    • 如果它是可重复使用的,我绝对会把它放在一个单独的脚本中;如果它只在这个特定的脚本中有用,内联它可以避免用随机的谷壳污染你的bin。还要注意find ... -exec {} \; 与通常更高效的find ... -exec {} + 之间的区别(尽管使用前者可以简化内部脚本)。
    【解决方案2】:

    失败的一个原因是,在双引号下用xargs 替换的命令甚至在前者执行之前就被shell 扩展了。避免这种情况的一种方法是在 sh -c as 创建的子 shell 内进行整个替换

    find "$dir" -name "*.txt.xy" -print0 | 
    xargs -0 -I {} sh -c '
      f="{}"
      g="$(echo "$f" | sed -e 's|"'^"${dir}"'"||' -e 's|"'\\"${suffix}"$'"||' )"
      program "$f" | subprogram filename="$g"
    '
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多