如何使用`sh -c`正确执行带有列表的命令?

时间:2017-03-05 14:46:10

标签: bash shell escaping sh

我有这个命令以递归方式查找包含typedef struct its_structure { uintptr_t data; ///< Either a pointer to the C string, or the actual ///< string, together with a bit to indicate which ///< of those it is. } its; its its_alloc(size_t size) { if (size < sizeof(uintptr_t)) { its const immediate_string = {.data = 0x01}; return immediate_string; } else { void * const memory = allocate_2byte_aligned(size); assert(IS_ALIGNED_2BYTE(memory)); its const allocated_string = { .data = memory ? (uintptr_t) memory : (0x01 | 0x02) /* Invalid string */}; return allocated_string; } } void its_free(its string) { if (IS_ALIGNED_2BYTE(string.data)) { free_2byte_aligned((void *) string.data); } // else immediate, thus no action neccessary } 但不包含mustExist.js的目录:

cannotExist.js

工作正常。

现在,我必须将其作为字符串传递给comm -13 <(find . -type f -name cannotExist.js -exec dirname {} \; | sort -u) <(find . -type f -name mustExist.js -exec dirname {} \; | sort -u) 自动化脚本。该脚本选取字符串并将其作为node.js运行。我无法改变这一部分。

所以我传递了这个字符串:

sh -c <string>

但是,我总是遇到这个错误:

'comm -13 <(find . -type f -name cannotExist.js -exec dirname {} \\; | sort -u) <(find . -type f -name mustExist.js -exec dirname {} \\; | sort -u)'

当我传递这个字符串时:

Warning: Command failed: /bin/sh -c comm -13 <(find . -type f -name cannotExist.js -exec dirname {} \; | sort -u) <(find . -type f -name mustExist.js -exec dirname {} \; | sort -u)
/bin/sh: 1: Syntax error: "(" unexpected

我明白了:

'"comm -13 <(find . -type f -name cannotExist.js -exec dirname {} \\; | sort -u) <(find . -type f -name mustExist.js -exec dirname {} \\; | sort -u)"'

当我手动尝试使用Warning: Command failed: /bin/sh -c "comm -13 <(find . -type f -name cannotExist.js -exec dirname {} \; | sort -u) <(find . -type f -name mustExist.js -exec dirname {} \; | sort -u)" /bin/sh: 1: comm -13 <(find . -type f -name cannotExist.js -exec dirname {} \; | sort -u) <(find . -type f -name mustExist.js -exec dirname {} \; | sort -u): not found 来模仿自动化脚本时:

sh

我得到了一个不同的错误:

sh -c comm -13 <(find . -type f -name cannotExist.js -exec dirname {} \; | sort -u) <(find . -type f -name mustExist.js -exec dirname {} \; | sort -u)

或引用:

comm: missing operand

我明白了:

sh -c "comm -13 <(find . -type f -name cannotExist.js -exec dirname {} \; | sort -u) <(find . -type f -name mustExist.js -exec dirname {} \; | sort -u)"

其他报价:

/bin/sh: 1: Syntax error: "(" unexpected

有可能以某种方式这样做吗?

1 个答案:

答案 0 :(得分:2)

您可以使用更简单,更高效的命令:

find . -type d -exec sh -c 'test -e "$1"/mustExist.js && ! test -e "$1"/cannotExist.js' _ {} \; -print

这会遍历目录,并检查每个目录中的所需文件,并确保禁止的文件存在。

一个示例,其中只有foo/bar3包含yes.js且不包含no.js

$ mkdir -p foo/bar1 foo/bar2 foo/bar3
$ touch foo/bar1/no.js foo/bar1/yes.js foo/bar2/no.js foo/bar3/yes.js
$ find foo -type d -exec sh -c 'test -e "$1"/yes.js && ! test -e "$1"/no.js' _ {} \; -print
foo/bar3

传递到您的脚本需要一些创意引用,但是:

somescript "find foo -type d -exec sh -c 'test -e \"\$1\"/yes.js && ! test -e \"\$1\"/no.js' _ {} \; -print"

如果您使用bash,可以稍微简化一下:

somescript $'find foo -type d -exec sh -c \'test -e "$1"/yes.js && ! test -e "$1"/no.js\' _ {} \; -print'

如果您愿意使用过时且可能不受支持的运算符-a,则可以将其减少为test的单个调用。

find . -type d -exec test -e {}/mustExist.js -a ! -e {}/cannotExist.js \; -print

传递给您的脚本也有点简单,因为它本身不包含任何引号:

somescript 'find . -type d -exec test -e {}/mustExist.js -a ! -e {}/cannotExist.js \; -print'

您也可以使用多个-exec原色来简化它:

somescript 'find . -type d -exec test -e {}/mustExist.js \; ! -exec test -e {}/cannotExist.js \; -print'

效率稍低(它运行test两次而不是一次)但更便于携带,而且比将字符串传递给sh -c的版本更容易引用。