我需要一个单行程序来重命名目录中的所有文件
某事.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
答案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
此命令用于sed
将mv
每个文件复制到具有相同名称但所有字符都是第一个的文件转为小写,则每个空格后跟任意字符的组合都会变为大写,然后第一个字符会变为大写。
覆盖之前将会进行询问。
-i
如果希望它自动覆盖,则删除。