Linux 一行程序将一个文件附加到另一个文件中,但仅当它没有';还没有添加
我有一个自动化流程,它有许多行,如以下模式:Linux 一行程序将一个文件附加到另一个文件中,但仅当它没有';还没有添加,linux,bash,shell,awk,sed,Linux,Bash,Shell,Awk,Sed,我有一个自动化流程,它有许多行,如以下模式: sudo cat /some/path/to/a/file >> /some/other/file 我想将其转换为一行程序,如果尚未添加/some/path/to/a/file,它将只附加到/some/other/file 编辑 很明显,我这里需要一些例子 示例1:为特定登录更新.bashrc脚本 示例2:为不同的登录创建.screenrc 示例3:追加到/etc/config文件的末尾 其他一些警告。文本将添加到块(>>)中。因此,查
sudo cat /some/path/to/a/file >> /some/other/file
我想将其转换为一行程序,如果尚未添加/some/path/to/a/file
,它将只附加到/some/other/file
编辑
很明显,我这里需要一些例子
示例1:为特定登录更新.bashrc脚本
示例2:为不同的登录创建.screenrc
示例3:追加到/etc/config文件的末尾
其他一些警告。文本将添加到块(>>)中。因此,查看是否在文件末尾添加了整个代码块应该相对简单。我试图想出一个简单的方法来确定文件是否已经附加到原始文件中
谢谢
python脚本示例
def check_for_added(新文件、原始文件):
“”“检查原始\u文件是否包含新\u文件的内容”“”
新的\u行=已反转(新的\u文件.split(“\n”))
原始\u行=已反转(原始\u文件.split(“\n”))
追加=无
对于新线路,拉链中的原始线路(新线路,原始线路):
如果是新线路!=原始线路:
追加=错误
打破
其他:
追加=真
附加的返回
EDIT:Op刚才在评论中告诉我,他想要连接的文件是bash脚本——这让我们回到了好的ole C预处理器,包括保护策略:
在每个文件前加上
if [ -z "$__<filename>__" ]; then __<filename>__=1; else
这样,您就可以在每个文件中的脚本周围进行一次测试,以确定某个文件是否包含另一个文件
contains_file_in_file() {
local small=$1
local big=$2
awk -v RS="" '{small=$0; getline; exit !index($0, small)}' "$small" "$big"
}
if ! contains_file_in_file /some/path/to/a/file /some/other/file; then
sudo cat /some/path/to/a/file >> /some/other/file
fi
也许这会让你开始-这个GNU awk脚本:
gawk -v RS='^$' 'NR==FNR{f1=$0;next} {print (index($0,f1) ? "present" : "absent")}' file1 file2
将告诉您“文件1”的内容是否存在于“文件2”中。它无法告诉您原因,例如,因为您以前将file1连接到file2的末尾
这就是你所需要的吗?如果没有,请更新您的问题以澄清/解释。这对您有用吗
sudo (set -o noclobber; date > /tmp/testfile)
noclobber防止覆盖现有文件
我想不会,因为你写了你想附加一些东西,但这种技术可能会有所帮助
当在一个脚本中发生全部追加时,请使用标志:
if [ -z "${appended_the_file}" ]; then
cat /some/path/to/a/file >> /some/other/file
appended_the_file="Yes I have done it except for permission/right issues"
fi
我将继续使用上面的内容编写一个函数appendOnce{..}
。如果你真的想要一条丑陋的单行线(丑陋:眼睛和同事的痛苦):
将此与sudo相结合:
test -z "${ugly}" && sudo "cat /some/path/to/a/file >> /some/other/file" && ugly="dirt"
看起来,您需要的是脚本段的集合,这些脚本段可以作为一个单元运行。您的方法(将它们放在一个文件中)很难维护,并且会受到各种竞争条件的影响,这使得它的实现很棘手 与大多数现代Linux发行版使用的方法类似,一种简单得多的方法是创建脚本目录,例如
~/.bashrc.d
,并将每个块作为单独的文件保存在该目录中
驱动程序(替换所有这些文件的连接)只是一次运行一个目录中的脚本:
if [[ -d ~/.bashrc.d ]]; then
for f in ~/.bashrc.d/*; do
if [[ -f "$f" ]]; then
source "$f"
fi
done
fi
要从骨架目录添加文件,只需创建一个新的符号链接
add_fragment() {
if [[ -f "$FRAGMENT_SKELETON/$1" ]]; then
# The following will silently fail if the symlink already
# exists. If you wanted to report that, you could add || echo...
ln -s "$FRAGMENT_SKELETON/$1" "~/.bashrc.d/$1" 2>>/dev/null
else
echo "Not a valid fragment name: '$1'"
exit 1
fi
}
当然,可以通过内容而不是名称对文件进行有效的索引。但在大多数情况下,按名称进行索引会更好,因为它对编辑脚本片段非常健壮。如果使用内容检查(例如md5sum),则可能会有相同片段的旧版本和新版本处于活动状态,并且没有明显的方法删除旧版本
但是,要使上述结构适应可能存在的任何需求和约束,应该是直截了当的
例如,如果无法使用符号链接(例如,因为骨架和实例不共享文件系统),则可以复制文件。如果文件已经存在并且具有相同的内容,您可能希望避免复制,但这只是为了提高效率,如果脚本片段很小,这可能不是很重要。或者,您可以使用
rsync
使骨架和实例彼此保持同步;这将是一个非常可靠和低维护的解决方案。我们如何判断?假设/some/path/to/a/file
只包含单词foo
,而/some/other/file
恰好已经包含单词foo
。我们如何判断foo
是否存在于/some/other/file
中,这是因为之前添加了/some/path/to/a/file
?提供更多解释,加上一些示例输入和预期输出。只是出于好奇:为什么只有一行?我的意思是,如果你在一个脚本中放几个命令,它也会是一行。@EdMorton给出了这个例子,文件的全部内容应该在一个块中。所以,不需要寻找单个单词。@purplehuman我可能错误地猜测这是一个容易解决的问题。感觉好像有人已经通过某种sed和awk的组合解决了这个问题。@Brian Bruggeman,我同意Ed Morton要求你做的事情,你可能也想看看。如果结果中需要两行代码,这是行不通的。如果其中一个文件有相同的行两次,结果将是错误的。我猜他希望他的内容是唯一的,因为他显然无法在不跟踪文件的情况下判断一个文件是否被添加到另一个文件中(除非他真的想在整个累加器文件中搜索作为“子字符串”的新文件).如果我说这些文件是系统文件和用户文件,会有区别吗?我正在调试vagrant和packer.io的配置脚本,如果出现故障,我想重新运行配置脚本cat/some/addition/to/bash\u rc
>>~/.bashrc
否。对不起。这里的问题是,您无法判断是否添加了文件
if [[ -d ~/.bashrc.d ]]; then
for f in ~/.bashrc.d/*; do
if [[ -f "$f" ]]; then
source "$f"
fi
done
fi
add_fragment() {
if [[ -f "$FRAGMENT_SKELETON/$1" ]]; then
# The following will silently fail if the symlink already
# exists. If you wanted to report that, you could add || echo...
ln -s "$FRAGMENT_SKELETON/$1" "~/.bashrc.d/$1" 2>>/dev/null
else
echo "Not a valid fragment name: '$1'"
exit 1
fi
}