Iva*_*van 6 command-line find text-processing files
我讨厌用许可/归属注释来混淆我的源代码文件,但有时这是必需的。因此,编写了数十个源代码文件(在子目录树中组织),我需要在每个文件的开头添加相同的多行注释。
我怀疑这是使用标准 GNU/Linux 命令行工具完成的一项非常容易的任务,尽管我几乎不擅长认真使用它们,因此请原谅并寻求您的帮助。
我需要的是更换每一个theTargetFile.txt中./*.txt(包括子目录递归)喜欢的东西cat theCommonComment.txt theTargetFile.txt。
我还希望排除适合特定更具体掩码的文件,例如考虑所有*.txt但*.DontTouch.txt保持完整。
我认为我真正需要的最难的部分是一个find基于奇特的咒语,它可以运行在子目录、包含*.txt文件和排除*.DontTouch.txt文件中。
最直接的方法,我可以看到这样做是GNU find,bash而sponge从实用moreutils:
find dir/with/files -name '*.txt' ! -name '*.DontTouch.txt' -print0 |
while IFS= read -rd '' file; do
echo 'cat path/to/theCommonComment.txt "$file" | sponge "$file"'
done
Run Code Online (Sandbox Code Playgroud)
就目前而言,这只会打印cat/sponge命令而不实际执行任何操作。一旦你确定你有你想要的东西,你可以删除命令周围的回声和单引号。
不使用sponge或-print0查找选项可能并非在所有系统上都可用:
find dir/with/files -name '*.txt' ! -name '*.DontTouch.txt' -exec sh '
for file; do
tempfile=$(mktemp)
cat path/to/theCommonComment.txt "$file" >"$tempfile"
mv "$tempfile" "$file"
done
' sh {} +
Run Code Online (Sandbox Code Playgroud)
没有简单的方法来阻止这个简单的打印它会做什么,所以要小心。需要注意的一件事 - 确保您的theCommonComment.txt文件不在您正在执行递归操作的目录中(或至少确保它被排除在查找之外),否则您最终会得到两个标题一些文件。
最后一个想法是您可能想要检查标题是否已添加到文件中。如果您添加新文件并且必须再次运行该命令,这可能很有用。它还解决了theCommonComment.txt在搜索路径中包含文件的问题。这两个解决方案将变成:
comment_file=path/to/theCommonComment.txt
size=$(wc -c "$comment_file")
find dir/with/files -name '*.txt' ! -name '*.DontTouch.txt' -print0 |
while IFS= read -rd '' file; do
if [ cmp -n "$size" $comment_file" "$file" ]; do
echo 'cat "$comment_file" "$file" | sponge "$file"'
fi
done
Run Code Online (Sandbox Code Playgroud)
export comment_file=path/to/theCommonComment.txt
export size=$(wc -c "$comment_file")
find dir/with/files -name '*.txt' ! -name '*.DontTouch.txt' -exec sh '
for file; do
if [ cmp -n "$size" $comment_file" "$file" ]; do
tempfile=$(mktemp)
cat "$comment_file" "$file" >"$tempfile"
mv "$tempfile" "$file"
fi
done
' sh {} +
Run Code Online (Sandbox Code Playgroud)
我会创建一个文件,其中dummy包含您要替换的内容。所以dummy文件如下所示。
<?php
/**
*
* Copyright (C) MyCompany, Ltd. - All Rights Reserved
* Unauthorized copying of this file, via any medium is strictly prohibited
* Proprietary and Confidential
*
*
*/
Run Code Online (Sandbox Code Playgroud)
之后,我将执行以下脚本。
for f in ./*; do
sed -i '/<?php/{
s/<?php//g
r dummy
}' $f
done
Run Code Online (Sandbox Code Playgroud)
我将其替换<?php为空格,并将其替换为文件中的内容dummy。
当然,您可以修改上面的代码以满足您的要求。
然而,有一种更复杂的方法可以做到这一点。
for f in *; do
echo "whatever" > tmpfile
cat $f >> tmpfile
mv tmpfile $f
done
Run Code Online (Sandbox Code Playgroud)
上面的答案取自这里。您基本上是先将内容放入 tmpfile,然后将原始内容添加到 tmpfile。完成后,您将 tmpfile 重命名回原始文件名。