简体   繁体   English

仅在文件开头没有找到+ sed追加行

[英]find + sed append line to beginning of file only if not there

I am writing a script that appends a line to the beginning of files in a directory. 我正在编写一个脚本,该脚本在目录中的文件开头添加一行。 The following code below does that. 下面的代码可以做到这一点。

 find . -type d \(  -name ThirdParty  -o  -name 3rdParty -o \
                    -name 3rd_party \) \
        -prune -o -type f \( -name "*.java"  -o -name "*.cs"    -o \
                             -name "*.cpp"   -o -name "*.cxx"   -o \
                             -name "*.cc"    -o -name "*.c"     -o \
                             -name "*.h"     -o -name "*.scala" -o \
                             -name "*.css"   -o -name "*.js" \) \
      -print0 | 
xargs -0 sed -i  '1s/^/\/*RIGHTS AND ETC ETC ETC/*'

However, I want to add this line ONLY if it is not already in the file. 但是,我只想添加此行(如果该行尚未在文件中)。 I have tried using grep and piping prior to using sed as such: 在使用sed之前,我曾尝试使用grep和管道:

grep -q "/*RIGHTS AND ETC ETC ETC/*" | sed -i....

but, when I run the script I get sed: no input files . 但是,当我运行脚本时,会被sed: no input files I am simply running this script in a directory so there are no input files. 我只是在目录中运行此脚本,所以没有输入文件。 Thank you. 谢谢。

Your grep command doesn't print anything, because you used the -q option; 您的grep命令不会打印任何内容,因为您使用了-q选项; it just sets the exit status based on whether the file matched. 它只是根据文件是否匹配来设置退出状态。

You want to print all the filenames that don't match, so you can pass those filenames to sed . 您要打印所有匹配的文件名,因此可以将这些文件名传递给sed You can do that with the -L option, along with -z to use a null terminator rather than newline (like the -print0 option in find ). 你可以做到这一点与-L选项,沿-z使用空终止符,而不是换行(如-print0在选项find )。

You should also use -F to treat the string as a fixed string, rather than a regular expression pattern. 您还应该使用-F将字符串视为固定字符串,而不是正则表达式模式。

find . -type d \( -name ThirdParty -o -name 3rdParty -o -name 3rd_party \) -prune \
    -o -type f \( -name "*.java" -o -name "*.cs" -o -name "*.cpp" -o -name "*.cxx" -o -name "*.cc" -o -name "*.c" -o -name "*.h" -o -name "*.scala" -o -name "*.css" -o -name "*.js" \) -print0 |
xargs -0 grep -Lz -F "/*RIGHTS AND ETC ETC ETC/*" |
xargs -0 sed -i ...

grep isn't needed. 不需要grep sed can do a negative search, and make the i nsert conditional: sed可以做一个消极的搜索,使i nsert条件:

... -print0 | xargs -0 sed -i '1{/^\/\*RIGHTS AND ETC ETC ETC\*\/$/!i\
/\*RIGHTS AND ETC ETC ETC\*/
}'

Notes: 笔记:

  • the linefeeds in the three lines of code are necessary for i to work correctly. 三行代码中的换行符对于i正常工作是必需的。

  • it's unclear whether the * s are literal or not, so they've been quoted like so \\* . 尚不清楚*是否为文字,因此它们的引用方式为\\*

This might work for you (GNU sed and find): 这可能对您有用(GNU sed和查找):

(var="/*RIGHTS AND ETC ETC ETC/*" ;
find whatever  \! -exec grep -qF "$var" {} \; -exec sed -i '1i\'"$var" {} \;)

Where whatever are the initial find commands. 其中whatever是初始查找命令。

This will only insert the variable var if the grep did not find var anywhere in each entire file. 仅当grep在每个整个文件的任何地方都找不到var时,才插入变量var

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM