在Linux中向多个文件末尾添加一些文本

58

如何在目录及其子目录中的多个php文件末尾添加以下代码:

</div>
<div id="preloader" style="display:none;position: absolute;top: 90px;margin-left: 265px;">
<img src="ajax-loader.gif"/>
</div>

我已经尝试过:

echo "my text" >> *.php

但终端显示错误:

bash : *.php: ambiguous redirect
6个回答

126

我通常使用"Tee",因为我认为它看起来更整洁,在一行内也比较容易放下。

echo "my text" | tee -a *.php

这是一个非常棒的答案。 :-) 由于 OP 正在使用 bash,设置 globstar 也将允许它处理子目录中的 PHP 文件。 - ghoti
如果我需要将一个字符串附加到多个特定文件中,该怎么办?我有多个WordPress安装,并且我需要在名为functions.php的每个文件末尾添加一个字符串。使用tee命令是否可行? - RobBenz
1
非常好,这也支持globstar,例如echo "my text" | tee -a **/*.php如果需要的话 :) - Mark
太棒了!喜欢它。 - thebiggestlebowski

26

你没有指定 shell,你可以尝试使用 foreach 命令。在 tcsh 中(我确定 bash 也有非常相似的版本),你可以像下面这样交互式地执行:

foreach i (*.php)
foreach> echo "my text" >> $i
foreach> end

$i会在循环的每一次中取到每个文件的名称。

通常,在对大量文件进行操作时,最好在包含样本文件的小目录中测试它们,以确保其按预期工作。

糟糕..错误消息中出现了bash(我会给你的问题打上这个标签)。等价的循环将是:

for i in *.php
do 
   echo "my text" >> $i
done

如果你想覆盖当前目录下的多个子目录,你可以指定

*/*.php

与其使用*.php,不如


子目录中的文件怎么办?我也需要对它们进行追加。 PS:我使用了以下命令: for i in $a do echo "the code" >> $i done 但是所有文件都被追加了两次,子目录中的文件没有任何变化。 - Harikrishnan
对于bash示例,请引用$i以处理文件名中包含空格的情况。 - David Farrell

23

BashFAQ/056做了很好的工作,解释了为什么你尝试的方法无效。请查看。

由于您正在使用bash(根据您的错误),因此 for 命令是您的朋友。

for filename in *.php; do
  echo "text" >> "$filename"
done

如果你想从文件中提取“文本”,你可以使用以下方法:

for filename in *.php; do
  cat /path/to/sourcefile >> "$filename"
done

现在...你可能会有子目录中的文件。如果是这样,你可以使用find命令来查找和处理它们:

find . -name "*.php" -type f -exec sh -c "cat /path/to/sourcefile >> {}" \;
find 命令使用 -name-type 等条件来识别哪些文件,然后 -exec 命令运行基本上与我在上一个 "for" 循环中展示的相同的内容。最后的 \; 表示对于 -exec 选项,这是参数的结束标志。
你可以通过 man find 获得更多关于此命令的详细信息。 find 命令是可移植的,并且通常建议在这种情况下使用,特别是如果您希望您的解决方案可以在其他系统中使用。但是,由于您当前正在使用 bash,您还可以使用 bash 的 globstar 选项处理子目录。
shopt -s globstar
for filename in **/*.php; do
  cat /path/to/sourcefile >> "$filename"
done
你可以通过 man bash 并搜索 "globstar" 以获取更多细节信息。此选项需要bash版本4或更高版本。
注意:你可能会遇到其他问题。PHP脚本不需要以 ?> 结尾,因此你可能正在添加HTML代码,而脚本会尝试将其解释为PHP代码。

它什么也没做。没有返回错误,但也没有在任何文件中追加任何行。 - Harikrishnan
我已经更新了命令,使其更加灵活。如果您向我们展示您的实际命令行,我们可能能够进行调试。 - ghoti

6
您可以使用 sedfind 结合使用。假设您的项目目录树为:
    /MyProject/ 
    /MyProject/Page1/file.php
    /MyProject/Page2/file.php
    etc.        
  1. Save the code you want to append on /MyProject/. Call it append.txt
  2. From /MyProject/ run:

    find . -name "*.php" -print | xargs sed -i '$r append.txt'
    

    Explain:

    • find does as it is, it looks for all .php, including subdirectories
    • xargs will pass (i.e. run) sed for all .php that have just been found
    • sed will do the appending. '$r append.txt' means go to the end of the file ($) and write (paste) whatever is in append.txt there. Don't forget -i otherwise it will just print out the appended file and not save it.

来源: http://www.grymoire.com/unix/Sed.html#uh-37

Sed是一种非常有用的文本处理工具,它可以对文件进行编辑,并在执行脚本时自动完成任务。Sed使用“替换”来编辑文件,并且可以从标准输入或文件中获取数据。Sed提供了一些命令来实现高级编辑功能,例如查找和替换、删除行或行范围、插入或追加文本以及更改行顺序。


3
您可以执行以下操作(即使文件路径中有空格):
#!/bin/bash

# Create a tempory file named /tmp/end_of_my_php.txt
cat << EOF > /tmp/end_of_my_php.txt
</div>
<div id="preloader" style="display:none;position: absolute;top: 90px;margin-left: 265px;">
<img src="ajax-loader.gif"/>
</div>
EOF

find . -type f -name "*.php" | while read the_file
do
    echo "Processing $the_file"
    #cp "$the_file" "${the_file}.bak" # Uncomment if you want to save a backup of your file
    cat /tmp/end_of_my_php.txt >> "$the_file"
done

echo
echo done

PS:您必须从要浏览的目录中运行脚本。


1
受@Dantastic答案启发:
echo "my text" | tee -a file1.txt | tee -a file2.txt

1
为了避免在终端中显示任何内容(例如在脚本中使用): echo "my text" | tee -a file1.txt | tee -a file2.txt >/dev/null - MrPotatoHead
你可以直接使用以下命令:echo "my text" | tee -a file1.txt file2.txt,无需再次使用管道操作。 - Peter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接