如何修改此 BAT 代码以适用于所有子文件夹?

问题描述 投票:0回答:2

我需要将标签应用于目录中的所有 .md 文件(用于 Obsidian),包括子文件夹中的所有 .md 文件。构建 this post 中的代码,我能够使用以下代码将其用于与 BAT 文件位于同一文件夹中的 .md 文件:

for %%f in (*.md) do (        
      echo #unpolished >>%%f
)

如果有人可以修改它以适用于所有子文件夹,我将不胜感激

虽然理想情况下,如果不是太困难,可以调整代码来做这两件事:

  1. 写入.md文件的开头
  2. 代替#unpolished 标签,是否可以添加此代码:
---
tags: unpolished
aliases:
cssclass:
---

第二部分太难了意义不大,以后有人补充不及时。我尝试过各种批处理命令、VBA 代码和 Notebook++,但我的经验有限,无法让它发挥作用。感谢您的帮助。

batch-file markdown obsidian
2个回答
1
投票

一般的做法是建立一个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如果找不到,则进行处理。


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;
}
© www.soinside.com 2019 - 2024. All rights reserved.