我想知道是否可以替换filename.ext
其内容中关于基于以下内容的模式的匹配模式:文件名本身使用sed
(也grep
可能?)。
让我向您展示一些您可以重新创建的文件作为示例:
cat > '[2022] Diary 2022 (essay, Travels).txt' <<\EOF
TITLE/- Diary 2022 (essay, Travels) -\TITLE
@
sometext...
EOF
cat > '[2022] Diary 2022 (list, Recipes).txt' <<\EOF
TITLE/- Diary 2022 (list, Recipes) -\TITLE
@
sometext...
EOF
cat > '[2022] Diary 2022 (watchlist, Movies-).txt' <<\EOF
TITLE/- Diary 2022 (watchlist, Movies-) -\TITLE
@
sometext...
EOF
cat > '[2022] Diary 2022 (list, Movies+).txt' <<\EOF
TITLE/- Diary 2022 (list, Movies+) -\TITLE
@
sometext...
EOF
我想要使用的匹配模式是(从右到左的人类阅读)之间的一切结束右括号和第一个遇到的空间。
我想说这个模式是基于位置, 而不是单词或者数字或者还要别的吗。
Foo Bar foobar(foob,匹配).ext
我认为这应该是正确的正则表达式>\(.+\s(\w.+)\)
我希望事情变成这样:
[2022] Diary 2022 (essay, Travels).txt
> 变为 >travels.txt
并且其内容变为 >
TITLE/- travels -\TITLE
@
sometext...
[2022] Diary 2022 (watchlist, Movies-).txt
> 变为 >movies-.txt
并且其内容变为 >
TITLE/- movies- -\TITLE
@
sometext...
[2022] Diary 2022 (list, Movies+).txt
> 变为 >movies+.txt
并且其内容变为 >
TITLE/- movies+ -\TITLE
@
sometext...
等等...
答案1
sed
无法进行此类文件重命名,因此您还需要其他东西,例如使用mv
.
bash
如果您有with的版本mapfile
,则重命名和修改都很简单:
模组文件
#!/bin/bash
set -o noclobber
for filename; do
if [[ $filename =~ ^'['[0-9]+']'[[:space:]]+(.*[[:space:]]([^[:space:]]+)')')'.txt'$ ]]; then
old='TITLE/- '${BASH_REMATCH[1]}' -\TITLE'
new='TITLE/- '${BASH_REMATCH[2]}' -\TITLE'
out=${BASH_REMATCH[2]}.txt
mapfile -d '' data <"$filename"
printf '%s' "${data//"$old"/"$new"}" >"$out"
# rm "$filename"
fi
done
$ chmod +x modfile
$ ./modfile *.txt
答案2
和zsh
:
rename_and_edit() {
{
printf 'TITLE/- %s -\\TITLE\n' $2:r &&
tail -n+2
} < $1 > $2 &&
rm -f -- $1
}
autoload -Uz zmv
zmv -P rename_and_edit '* (*)\)(.txt)' '$1:l$2'
无论第一行包含什么内容,都会用新标题替换文件的第一行。要将所有出现的旧标题替换为新标题,无论它们出现在哪里:
zmodload zsh/mapfile
rename_and_edit() {
local oldtitle="TITLE/- $1:r -\\TITLE" \
newtitle="TITLE/- $2:r -\\TITLE"
print -rn -- ${mapfile[$1]//$oldtitle/$newtitle} > $2 &&
rm -f -- $1
}
autoload -Uz zmv
zmv -P rename_and_edit '* (*)\)(.txt)' '$1:l$2'
或者:
zmodload zsh/mapfile
rename_and_edit() {
3=( 'TITLE/- '$^@:r' -\TITLE' )
print -rn -- ${mapfile[$1]//$3/$4} > $2 &&
rm -f -- $1
}
autoload -Uz zmv
zmv -P rename_and_edit '* (*)\)(.txt)' '$1:l$2'