替换当前目录及子目录下所有.py文件中的代码
# 替换当前目录及子目录下所有.py文件中的代码
find . -type f -name "*.py" -exec sed -i 's/旧代码/新代码/g' {} +
各部分含义:
-
-type f
-
表示只查找普通文件(file)
-
排除目录(
-type d
)、符号链接等其他类型的文件系统对象
-
-
{}
-
这是
find
命令的占位符,表示被找到的文件名 -
当
find
执行-exec
后面的命令时,会用实际找到的文件名替换{}
-
例如找到
a.py
和b.py
,{}
会被替换为这两个文件名
-
-
+
-
表示将多个找到的文件一次性传递给后面的命令(这里是
sed
) -
替代写法是
\
;(分号需要转义),但\
; 会对每个文件单独执行命令,效率较低 -
+
的批处理方式更高效,相当于把多个文件名一起传给sed
-
对比两种 -exec 结尾:
-
-exec command {} +
:多个文件一起处理(高效) -
-exec command {} \
;:每个文件单独处理(低效)
完整解释: 这条命令的意思是:
1. 从当前目录(`.`)开始递归查找
2. 只找普通文件(`-type f`)
3. 文件名匹配 `*.py`(`-name "*.py"`)
4. 对找到的所有文件执行 `sed` 替换命令(`-exec ...`)
5. `sed -i` 表示直接修改原文件
6. `'s/旧代码/新代码/g'` 是 `sed` 的替换语法(全局替换)
示例:
假设目录中有 a.py
和 b.py
,实际执行效果类似于:
sed -i 's/旧代码/新代码/g' a.py b.py
注意事项:
-
-i 选项会直接修改原文件,建议先不加
-i
测试(去掉-i
会打印结果但不修改文件) -
如果文件名包含特殊字符(如空格),使用
{} +
也能正确处理 -
macOS 的
sed
需要写成sed -i ''
(多一个空参数)
要替换当前目录下所有 .md 文件中的 (./.webp) 为 (.webp)(其中 *** 代表任意字符),你需要使用 正则表达式 来匹配和替换。
命令如下:
find . -type f -name "*.md" -exec sed -i 's#(\./\(.*\)\.webp)#(\1.webp)#g' {} +
关键点解析:
-
find . -type f -name "*.md"
- 查找当前目录(
.
)及其子目录下的所有.md
文件。
- 查找当前目录(
-
sed -i 's#...#...#g'
-
-i
:直接修改文件(不加-i
可以先测试,不修改原文件)。 -
s#...#...#g
:使用#
作为分隔符(因为路径里有/
,避免冲突)。
-
-
正则表达式匹配 (./***.webp)
-
(\./\(.*\)\.webp)
分解:-
\(.*\)
:匹配任意字符(*** 部分),并保存为 \1(反向引用)。 -
\./
:匹配./
(.
需要转义,否则匹配任意字符)。 -
\.webp
:匹配.webp
(.
需要转义)。
-
-
-
替换为 (***.webp)
(\1.webp)
:\1 代表前面\(.*\)
匹配到的内容(即 ***)。
示例: 假设 test.md 中有:


运行命令后,会变成:


注意事项:
- 测试命令(不修改文件):
find . -type f -name "*.md" -exec sed 's#(\./\(.*\)\.webp)#(\1.webp)#g' {} +
- 去掉 -i,只打印替换后的结果,不会修改文件。
- macOS 用户:
find . -type f -name "*.md" -exec sed -i '' 's#(\./\(.*\)\.webp)#(\1.webp)#g' {} +
- macOS 的
sed
需要-i ''
(多一个空参数)。
- 如果路径有特殊字符(如空格、# 等),建议用 find -print0 + xargs -0:
find . -type f -name "*.md" -print0 | xargs -0 sed -i 's#(\./\(.*\)\.webp)#(\1.webp)#g'
这样就能批量移除 .md 文件中的 ./,只保留 (***.webp) 格式。
**如果你只想把 (./ 替换成 ((即仅删除 ./),而保留后面的 *.webp) 不变,可以使用更简单的 sed 命令:
find . -type f -name "*.md" -exec sed -i 's#(\./#(#g' {} +
解析:
-
s#(\./#(#g
:-
(\./
→ 匹配(./
((
是普通字符,\.
匹配.
,/
是普通字符)。 -
(
→ 替换成(
(即仅删除./
)。 -
g
→ 全局替换(一行中所有匹配都会被替换)。
-
示例: 假设 test.md 内容:


运行命令后,变成:


注意事项:
- 测试命令(不修改原文件):
find . -type f -name "*.md" -exec sed 's#(\./#(#g' {} +
- macOS 用户:
find . -type f -name "*.md" -exec sed -i '' 's#(\./#(#g' {} +
如果路径有空格或特殊字符,建议用 find -print0 | xargs -0
:
find . -type f -name "*.md" -print0 | xargs -0 sed -i 's#(\./#(#g'
总结:
-
仅删除
./
→sed 's#(\./#(#g'
-
删除
./
并保留文件名(如原问题)→sed 's#(\./\(.*\)\.webp)#(\1.webp)#g'
-
s#(./#(#g 使用了 # 作为分隔符,而不是常见的 /。这是为了避免和模式中的 / 字符冲突,使正则表达式更清晰
批量替换Hugo内容目录中所有Markdown文件的图片相对路径为绝对路径,可以按照以下步骤操作
使用find命令结合Shell脚本动态替换路径:
find content/archives -type f -name "*.md" -exec sh -c '
file="$0"
dir=$(dirname "$file")
rel_path=$(echo "$dir" | sed "s|^content/archives/||")
sed -i.bak "s|!\[\](\([^)]*\.web\))|!\[\](archives/$rel_path/\1)|g" "$file"
' {} \;
操作说明
-
遍历文件:
find
命令查找content/archives
下所有.md
文件。 -
提取路径:获取每个文件相对于
content/archives
的目录路径(如2002/subdir1/subdir2
)。 -
替换路径:使用
sed
将
替换为
。
注意事项
-
路径验证:替换后的路径形如
archives/2002/subdir/.../file.web
,确保该路径在站点中有效。 -
前导斜杠:若需绝对URL路径,将替换部分改为

(添加斜杠)。 -
备份文件:脚本会生成
.bak
备份文件,处理完毕后可运行find content/archives -name "*.bak" -delete
清理。 -
扩展名适配:如需处理其他图片格式(如
.png
),修改正则中的.web
为.\(web\|png\|jpg\)
。
示例效果
文件content/archives/2002/a/b/post.md
中的:

将被替换为:

执行前请务必备份内容目录,测试无误后再应用到全部文件。
如果![]()
的[]
中有不同的内容而只要修改替换()
中的内容可按以下方案操作:
精准替换方案(保留 Alt 文本)
find content/archives -type f -name "*.md" -exec sh -c '
file="$0"
dir=$(dirname "$file")
# 提取从 archives 开始的相对路径(如 2002/subdir1/subdir2)
rel_path=$(echo "$dir" | sed "s|^content/archives/||")
# 精准替换括号内的路径,保留 Alt 文本
sed -i.bak "s|(\\([^)]*\\.web\\))|(archives/$rel_path/\\1)|g" "$file"
' {} \;
关键改进点
-
精准匹配
(\\([^)]*\\.web\\))
仅匹配括号内的.web
路径,保留![描述]
中的 Alt 文本不变。 -
动态路径插入
rel_path
变量会自动提取 MD 文件所在的层级路径(如2002/subdir1/subdir2
),并插入到图片路径中。 -
保留原始结构 替换后的路径格式为:
archives/2002/subdir1/subdir2/0.web
,与你的目录结构完全一致。
操作步骤
-
终端执行命令 复制上述脚本到终端运行,自动处理所有 .md 文件。
-
验证替换结果 示例文件
content/archives/2002/a/b/post.md
中的:


会被替换为:


- 清理备份文件 确认无误后执行清理:
find content/archives -name "*.md.bak" -delete
常见问题排查
- 路径未生效
-
检查
rel_path
是否正确:在脚本中添加echo "Processing: $file → $rel_path"
输出路径调试。 -
确保 Hugo 的
static/
目录或发布配置能正确映射archives/
路径。
-
特殊字符问题 如果路径含空格或特殊符号,在
sed
中用双引号包裹变量:"archives/$rel_path/\\1"
。 -
多格式支持 如需适配
.png
、.jpg
,修改正则表达式为:
sed -i.bak "s|(\\([^)]*\\.\\(web\\|png\\|jpg\\)\\))|(archives/$rel_path/\\1)|g" "$file"
执行示例
# 测试单个文件(替换前预览)
sed "s|(\\(.*\.web\\))|(archives/2002/a/b/\1)|g" post.md
# 实际执行(全量替换)
find content/archives -type f -name "*.md" -exec sh -c '...' {} \;
此方案确保仅修改括号内的图片路径,完美保留 Markdown 原有结构和 Alt 描述文本。