$ ls *
2000-01-01-abcd.md
2000-01-01-cdef.md
我可以从以下命令中提取 abcd 和 cdef
find *.md -exec sh -c "echo {} | sed 's/.md//' | sed 's/2000-01-01-//'" \;
我知道如何通过 在文件开头添加字符串sed '1s/^/string/'
,但如何传递确切的字符串?
我如何在相应的文件中传递这个字符串“abcd”和“cdef”,因为我想在每个文件的开头添加相应的字符串。
答案1
在每个文件的开头添加相应的字符串
巴什+sed方法:
for f in *.md; do fn=${f##*-}; sed -i "1 s/^/${fn%.*} /" "$f"; done
fn=${f##*-}
- 截断从左侧到最后一次出现的最长匹配序列-
(例如abcd.md
)${fn%.*}
- 截断最右边的序列(从末尾开始)直到.
前一个子字符串fn
(即abcd
)第一次出现(点)sed -i "1 s/^/${fn%.*} /" "$f"
- 将所需的字符串添加到文件的开头
答案2
我发现这最接近我正在寻找的东西。 tmp 缓冲区的想法解决了这个目的。其他解决方案暗示了 for 循环,在我看来, find -exec 组合已经解决了这一问题。
https://unix.stackexchange.com/a/197400/119007
find ./ -name '*.md' -exec sh -c "echo '{}' | sed 's/.md//' | sed 's/2000-01-01-//' > tmp && cat {} >> tmp && mv tmp {}" \;
答案3
您需要在命令*.md
中引用find
,否则在运行时它将扩展为匹配的名称。您也不应该{}
在引用的上下文中使用(参见例如是否可以安全地使用“find -exec sh -c”?)。
这是一个 shell 循环解决方案:
for name in ./*.md; do
prefix="${name%.md}" # "./2000-01-01-abcd.md" --> "./2000-01-01-abcd"
prefix="${prefix##*-}" # "./2000-01-01-abcd" --> "abcd"
{ echo "$prefix"; cat "$name"; } >"$name".tmp && mv "$name".tmp "$name"
done
同样的事情find
:
find . -type f -maxdepth 1 -name "*.md" \
-exec sh -c 'p="${1%.md}";p="${p##*-}";{ echo "$p";cat "$1"; }>"$1".tmp && mv "$1".tmp "$1"' sh {} ';'