在 Bash 中重命名为首字母大写或首字母大写

在 Bash 中重命名为首字母大写或首字母大写

我需要一个单行程序来重命名目录中的所有文件

某事.TXT
不是文件.ogg
敏感的lalala.doc

某事.txt
不是一个文件.ogg
敏感的Lalala.doc

换句话说:单词的首字母大写,其他字母小写。这称为起始字母或首字母大写。它与“标题大小写”非常接近。文件扩展名应为小写。

大多数现有问题似乎只涉及大写.MKV或者小写字母.mkv文件名,似乎没有一个涵盖大写字母.mkv例子)。

所有常见工具如管道、、sed等都perl可以grep使用。

答案1

rename如果您有权访问 perl rename(在基于 Debian 的系统上默认安装,perl-rename在许多其他系统上也可用),您可以运行:

rename  's/.*/lc($&)/e; s/(^| )./uc($&)/ge' *

解释:

程序rename将对每个输入文件名运行 perl 表达式。这里,第一个替换操作 ( s///) 将.*用其自身($&匹配的内容)替换所有内容 ( ),但小写 ( lc($&))。第二个替换操作将匹配空格后或文件名开头的每个字符 ( (^| )),并将其替换为其大写版本 ( uc($&))。

使用-n标志运行测试而不做任何更改:

$ rename -n 's/.*/lc($&)/e; s/ ./uc($&)/ge' *
rename NOT A FILE.ogg not A File.ogg
rename sensitive lalala.doc sensitive Lalala.doc
rename SomeThing.TXT something.txt

您还可以使用 shell 循环和 perl:

for f in *; do 
    mv "$f" "$(perl -lpe 's/.*/lc($&)/e; s/(^| )./uc($&)/ge' <<<"$f")"
done

这与上面的命令相同rename,只是我们将目录中的每个文件都输入进去,然后使用命令替换重新命名。

您可以轻松修改它以避免覆盖现有文件:

for f in *; do 
    target="$(perl -lpe 's/.*/lc($&)/e; s/(^| )./uc($&)/ge' <<<"$f")"; 
    [ -e "$target" ] && 
        echo "File \"$target\" exists, skipping \"$f\"" || 
        mv "$f" "$target"; 
done

答案2

“去大写”回答这里

for i in *
do
  mv "$i" "$( echo $i | tr '[:upper:]' '[:lower:]')"
done

大写已经回答这里

for i in *
do
  mv "$i" "$( echo $i | sed 's/[ ]*/\u&/g')"
done

答案3

这适用Bash 3.2.57于 Mac OSX

预览(没有任何改变):

IFS=$'\n';FOLDER=new;for F in $(ls -1);do EXT="${F##*.}";NAME="${F%.*}";NEW=$(echo "$NAME"| perl -pe 's/[ _-]([A-z0-9])([^ _-]+)/ \U\1\L\2/g');echo "cp '$F' '$FOLDER/$NEW.$EXT'";done

如果预览看起来不错,您可以使用它来重命名并 cp 到子文件夹中:

IFS=$'\n';FOLDER=new;[ -d $FOLDER ] || mkdir $FOLDER;for F in $(ls -1);do EXT="${F##*.}";NAME="${F%.*}";NEW=$(echo "$NAME"| perl -pe 's/[ _-]([A-z0-9])([^ _-]+)/ \U\1\L\2/g');cp -v "$F" "$FOLDER/$NEW.$EXT";done

笔记:

  • 不会改变文件扩展名。
  • 应该正确处理数字。
  • 如果您有其他字符想要转换为空格,只需将它们添加到字符类中:[ _-]
  • 避免名称冲突,方法是复制将每个文件的副本放入子文件夹中。这样你就有了“撤消”选项。另一种处理方法是重命名所有文件,同时添加一个前缀,如_My New File Name.jpg,然后将所有这些文件重命名为不带 的版本_

答案4

我想出了一个单行形式的快速解决方案:

for f in *; do mv -i "$f" "`echo $f | sed -e 's/\(.*\)/\L\1/' -e 's/\( .\)/\U\1/g' -e 's/\(^.\)/\U\1/g'`"; done

或者以可读的形式(但复制粘贴起来稍微不太舒服):

for f in *; do 
    mv -i "$f" "`echo $f | 
     sed -e 's/\(.*\)/\L\1/' -e 's/\( .\)/\U\1/g' -e 's/\(^.\)/\U\1/g'`"; 
done

此命令用于sedmv每个文件复制到具有相同名称但所有字符都是第一个的文件转为小写,则每个空格后跟任意字符的组合都会变为大写,然后第一个字符会变为大写。

覆盖之前将会进行询问。

-i如果希望它自动覆盖,则删除。

相关内容