2017-03-05 162 views
0

我有這個命令遞歸查找包含mustExist.js目錄,但不cannotExist.js如何正確使用`sh -c`執行帶有列表的命令?

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到immitate自動化腳本:

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 

其他報價:

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

「如果使用名稱sh調用bash,它會盡可能地模仿歷史版本sh的啓動行爲」(來源:man bash)。 sh並沒有很多bash的特性,我認爲命令結果擴展就是其中之一。可能的解決方法:把你的命令放在一個文件中,比如說my_find.sh,然後用'sh -c「bash -c my_find.sh」' –

+0

運行它謝謝@marekjancuska你一定是對的。該列表格式在'sh'中無效。 – Redsandro

回答

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的版本更容易引用。

+0

這實際上相當不錯!執行'sh'的第一個有點棘手,命令本身是由'sh'執行的,我需要將輸出轉發到'sh'(不是在問題中),所以這將是一個令人討厭的轉義工作。然而,你最後的命令真​​棒。我不知道'-exec'可以像這樣鏈接。這解決了我的問題,所以我想將其標記爲已接受的答案,但這在技術上不是我的具體問題的答案。我希望StackOverflow警察不會爲此懲罰我。 – Redsandro