我有许多 HTML 文件,它们都嵌套在单个整体文件夹中包含的不同文件夹中。在每个 HTML 文件中我需要替换
/contact/index.html
和
/contact/index.php
有没有一种简单的方法可以从命令行执行此操作?
答案1
是的,如果您有 GNUfind
和 GNU sed
,请在父文件夹中尝试以下操作:
find . -type f \( -iname "*.htm" -o -iname "*.html" \) -exec sed -i.bak 's#/contact/index\.html#/contact/index.php#' '{}' +
这将找到名称以.html
or.HTML
或.htm
or .HTM
(或.HtM
...) 结尾的所有文件,并对sed
它们运行以下命令:
sed -i.bak 's#/contact/index\.html#/contact/index.php#g'
foo.htm
这将进行您想要的替换并创建名为的原始备份foo.htm.bak
。如果您不需要备份,只需删除.bak
.
细节:
find
显然,该命令查找文件或文件夹。它的语法可能非常复杂,并在man page
下面复制的一些语法中进行了详细解释:
一般格式为find [where] [what]
.在上面给出的示例中,where
is.
表示当前目录。这what
是具有html
或类似扩展名的所有文件,因此我使用的iname
是:
-iname pattern
Like -name, but the match is case insensitive.
For example, the patterns `fo*' and `F??'
match the file names `Foo', `FOO', `foo',
`fOo', etc.
但是,我希望它能够匹配两者html
,htm
因此我使用该-o
标志,这意味着:
expr1 -o expr2
Or; expr2 is not evaluated if expr1 is true.
这些结构需要通过括号来分组在一起( )
,但是,需要逃脱了从 shell 中我们使用\(
和\)
。
魔法发生在以下-exec
部分:
-exec command ;
Execute command; true if 0 status is returned.
All following arguments to find are taken to
be arguments to the command until an argument
consisting of `;' is encountered. The string
`{}' is replaced by the current file name
being processed everywhere it occurs in the
arguments to the command, not just in argu‐
ments where it is alone, as in some versions
of find. [...] The specified command is
run once for each matched file. The command
is executed in the starting directory. There
are unavoidable security problems surrounding
use of the -exec action; you should use the
-execdir option instead.
换句话说,给定类似 的命令-exec ls {}
,find
将找到与您设置的条件匹配的所有文件并迭代它们,替换{}
为当前文件名并执行给定的命令。我还使用+
而不是\;
结束exec
调用,因为这将导致find
尝试运行尽可能少的命令,这只是一个小的优化,除非您有数千个文件,而这可能很重要:
-exec command {} +
This variant of the -exec action runs the
specified command on the selected files, but
the command line is built by appending each
selected file name at the end; the total num‐
ber of invocations of the command will be much
less than the number of matched files. The
command line is built in much the same way
that xargs builds its command lines. Only one
instance of `{}' is allowed within the com‐
mand. The command is executed in the starting
directory.
最后,sed
是一个命令行文本流编辑器,它将应用您给它的命令到文件的每一行。在这种情况下,命令是替换,基本格式是:
s#pattern#replacement#flags
分隔符 ( #
) 可以是任何特殊字符,并且传统上是这样,/
但我选择了,#
因为否则我将不得不转义/
.请注意,ChrisDown 在他的回答中选择使用|
.这只是个人选择,两者是等价的。
答案2
假设你有 GNU sed
:
find -iname '*.html' -type f -exec sed -i 's|/contact/index\.html|/contact/index.php|g' {} +