当目标文件需要空格时批量重命名

当目标文件需要空格时批量重命名

我需要根据标题名称使用随机名称重命名一批 Markdown 文件,并且目标名称需要带有空格(这是规范)。我正在尝试这个单行

for i in *;
do mv $i $(grep \# $i | head -1 | sed 's/# //' | sed 's/[_\?\!\]//' | sed 's/[:/]/ - /') ; 
done

但我在空格名称中收到“目标 X 不是目录”错误。

有小费吗?

答案1

主要问题是命令替换没有被引用,因此它被分成不同的参数,并且每个参数都受路径名扩展的影响(后一部分在bash,但不是zsh),并且当mv看到两个以上时,它假设最后一个是将文件移动到的目录。

出于同样的原因,$i它本身应该被引用(在 中bash),并且为了避免某些文件名以破折号开头的问题-,您应该在模式中使用./*in 代替*,或者将选项结束标记放在命令--mv

另外,我认为我们可以稍微简化一下处理文件名的方式。首先,sed可以接受多个命令,因此您只需调用一次。您可能还想添加/g到命令的末尾s///,以替换所有匹配项,而不仅仅是第一个匹配项。另请注意,其中 3 个反斜杠中有 2 个[_\?\!\]是多余的。[_?!]如果您想匹配_, ?or !or[_\?!]如果您还想包含反斜杠(尽管[_\\?!]使用某些实用程序会使其更加万无一失),请使用。

for f in ./*; do
    mv -- "$f" "$(grep \# "$f" | head -1 | sed -e 's/# //g' -e 's/[_?!]//g' -e's/[:/]/ - /g')"
done

您还可以将grepand组合head到 the 中sed

for f in ./*; do
    mv -- "$f" "$(sed -ne '/^# / {s///; s/[_?!]//g; s/[:/]/ - /g; p; q;}' < "$f")"
done

在这里,里面的命令{}以模式为条件/^# /q最后在该块的末尾退出脚本,因此仅处理第一个匹配行。

同样在awk

awk '/^# / { sub(/# /, ""); gsub(/[_?!]/, ""); gsub(/[:/]/, " - "); print; exit }' < "$f"

我还可以将最后一个替换更改为s/[:/] */ - /,这样像这样的字符串blah: bleh就会变成blah - blah, 而不是blah - bleh(破折号后有两个空格)。

答案2

只需在目标名称周围添加引号即可:

 mv $i "$(grep \# $i | head -1 | sed 's/# //' | sed 's/[_\?\!\]//' | sed 's/[:/]/ - /')" ; 

相关内容