Replace

遞歸目錄中的快速字元串替換

  • March 30, 2018

如何使用帶有空格單引號遞歸目錄和文件名進行快速文本替換?最好使用標準 UNIX 工具,或者使用眾所周知的軟體包。

使用find對於許多文件來說非常慢,因為它為每個文件生成一個新程序,所以我正在尋找一種將目錄遍歷和字元串替換集成為一個操作的方法。

慢搜尋:

find . -name '*.txt'  -exec grep foo {} \;

快速搜尋:

grep -lr --include=*.txt foo

慢換:

find . -name '*.txt' -exec perl -i -pe 's/foo/bar/' {} \;

快速更換:

# Your suggestion here

(這個相當快,但是是兩次通過並且不處理空格。)

perl -p -i -e 's/foo/bar/g' `grep -lr --include=*.txt foo`

您只想使用:

find . -name '*.txt'  -exec cmd {} \;

形式為那些cmd只能接受一個參數的 s。情況並非如此grep。與grep

find . -name '*.txt'  -exec grep foo /dev/null {} +

(或-H與 GNU 一起使用grep)。更多關於遞歸 grep 與 find / -type f -exec grep {} ; 哪個更高效/更快?

現在進行替換,同樣的,perl -pi可以採用多個參數:

find . -name '*.txt' -type f -exec perl -pi -e s/foo/bar/g {} +

現在這將重寫文件,無論它們是否包含foo。相反,您可能想要(假設 GNUgrepxargs/或兼容):

find . -name '*.txt' -type f -exec grep -l --null foo {} + |
  xargs -r0 perl -pi -e s/foo/bar/g

或者:

grep -lr --null --include='*.txt' foo . |
  xargs -r0 perl -pi -e s/foo/bar/g

所以只有包含的文件foo被重寫。


順便說一句,--include=*.txt--include作為另一個 GNU 擴展)是一個 shell glob,所以應該被引用。例如,如果--include=foo.txt在目前目錄中有一個文件被呼叫,shell 會--include=*.txt在呼叫grep. 如果沒有,對於許多 shell,您會收到關於 glob 無法匹配任何文件的錯誤。

所以你想要grep --include='*.txt'

引用自:https://unix.stackexchange.com/questions/434361