我需要将标签应用于目录中的所有 .md 文件(用于 Obsidian),包括子文件夹中的所有 .md 文件。构建 this post 中的代码,我能够使用以下代码将其用于与 BAT 文件位于同一文件夹中的 .md 文件:
for %%f in (*.md) do (
echo #unpolished >>%%f
)
如果有人可以修改它以适用于所有子文件夹,我将不胜感激
虽然理想情况下,如果不是太困难,可以调整代码来做这两件事:
---
tags: unpolished
aliases:
cssclass:
---
第二部分太难了意义不大,以后有人补充不及时。我尝试过各种批处理命令、VBA 代码和 Notebook++,但我的经验有限,无法让它发挥作用。感谢您的帮助。
一般的做法是建立一个filename-lister
for /f "delims=" %%b in ('dir /b /s /a-d filemask') do (
)
这将执行
dir
命令,忽略与文件掩码匹配的文件的目录名(/a-d
)(在您的情况下为*.md
),扫描子目录(/s
)并以基本形式列出(/b
),即,没有页眉、页脚或详细信息 - 只有名称。在树中的所有文件的内存中构建一个列表,然后找到的每个文件名依次分配给%%b
。
delims=
关闭默认的 for /f
处理为标记(参见文档提示中的 for /?
- 或数百个 SO 响应)因此整个文件名被分配给 %%b
I prefer to avoid ADFNPSTXZ (in either case) as metavariables (loop-control variables)
ADFNPSTXZ are also metavariable-modifiers which can lead to difficult-to-find bugs
(See `for/f` from the prompt for documentation)
由于
%%b
包含文件的完整绝对路径,它可能包含空格或其他混淆字符,所以使用时最好使用"quote the filename"
。这克服了大多数问题。
下一步是创建一个包含所需前缀数据的临时文件,因为尝试在文件开头插入是冒险的。
echo --->tempfile.###
echo tags: unpolished>>tempfile.###
echo aliases:>>tempfile.###
echo cssclass:>>tempfile.###
echo --->>tempfile.###
会那样做-请注意,在第一行中只有ONE
>
。这将启动一个新文件,因此如果存在现有的tempfile.###
,它将被覆盖。 >>
附加到文件中。
但是
这是非常低效的,因为每个
echo
语句都会打开、写入和关闭文件。
(
echo ---
echo tags: unpolished
echo aliases:
echo cssclass:
echo ---
)>tempfile.###
只打开、写入和关闭一次——而且更易于阅读和维护。请注意,
echo
es 包含在括号之间(…)
.
然后将您在
%%b
中选择的文件附加到临时文件
type "%%b">>tempfile.###
所以临时文件包含序言数据和原始文件,
然后使用
move
临时文件原件替换原件。
move tempfile.### "%%b"
因为这是一个批处理文件,不需要
/y
开关来绕过覆盖文件的确认,但是包含它也没有坏处。
move /y tempfile.### "%%b"
这将生成可以通过将
>nul
和/或 2>nul
附加到 move
命令行来抑制的消息。 >nul
抑制正常消息 (1 file(s) moved
) 和 2>nul
抑制错误消息。
就是这样。在文件名列表器中,在临时文件中创建序言,将原始文件附加到临时文件并将生成的临时文件移动到原始文件上。
强制性警告:在应用于真实数据之前,始终对照测试目录进行验证。
有用的扩展:
如果您多次运行此过程,每个文件将获取序言的另一个副本。
findstr /x /c:"tags: unpolished" "%%b" >nul
if errorlevel 1 (
rem did not fine "tags: unpolished" as a line in the file, so insert it
...
) else (echo skipping "%%b" - already processed)
将尝试在文件
%%b
中找到与常量字符串(/x
)完全匹配的行/c:string
,如果找到则将errorlevel
设置为0
,因此不处理或非0如果找不到,则进行处理。
这是一个 perl 脚本的示例,它将更新给定目录及其子目录中的所有
.md
文件:
#! /usr/bin/env perl
use Object::Pad;
use feature qw(say);
use strict;
use warnings;
{
die "Bad arguments. Please give start directory name" if @ARGV != 1;
my $start_directory = shift @ARGV;
my $self = Main->new(dir => $start_directory);
$self->update_all_md_files_with_tag();
}
class Main;
field $_dir :param;
use feature qw(say);
use File::Find;
method update_all_md_files_with_tag() {
find(sub {$self->wanted($_)}, $_dir);
say "Done.";
}
method wanted($fn) {
return if !(-f $fn);
return if $fn !~ /\.md\z/;
$self->add_tag($fn);
}
method read_file($fn) {
open (my $fh, "<", $fn) or die "Could not open file '$fn': $!";
my $str = do {local $/; <$fh>};
close $fh;
return $str;
}
method add_tag( $fn ) {
my $content = $self->read_file($fn);
$self->update_file_content_with_frontmatter(\$content);
## TODO: remember to take backup of all files before running this script!!
$self->write_file( $fn, \$content );
say ".. $fn";
}
method write_file( $fn, $content ) {
open (my $fh, ">", $fn) or die "Could not open file '$fn': $!";
print $fh $$content;
close $fh;
}
method get_frontmatter_template {
return <<"END";
---
tags: unpolished
aliases:
cssclass:
---
END
}
method update_file_content_with_frontmatter($content) {
my $frontmatter = $self->get_frontmatter_template();
$$content = $frontmatter . $$content;
}