我想用 awk/sed/bash 将小写文件名更改为大写
您的帮助将不胜感激
aaaa.txt
vvjv.txt
acfg.txt
期望的输出
AAAA.txt
VVJV.txt
ACFG.txt
前言:
如果您不关心扩展的大小写,只需在 shell 循环中使用 'tr' 实用程序:
for i in *.txt; do mv "$i" "$(echo "$i" | tr '[a-z]' '[A-Z]')"; done
如果您确实关心扩展的情况,那么您应该知道有不止一种方法可以做到这一点(TIMTOWTDI)。就个人而言,我相信这里列出的Perl解决方案可能是 Linux 下最简单、最灵活的解决方案。如果您有多个文件扩展名,只需指定您希望保持不变的数字。BASH4解决方案也是一个很好的解决方案,但您必须愿意将扩展名写出几次,或者使用另一个变量来存储它。但是,如果您需要严重的可移植性,那么我建议使用八进制的这个答案中的最后一个解决方案。某些版本的 Linux 还附带了一个名为rename的工具这也可能值得一试。它的用法因发行版而异,因此请键入man rename
以获取更多信息。
解决方案:
使用Perl:
# single extension
perl -e 's/\.[^\.]*$/rename $_, uc($`) . $&/e for @ARGV' *.txt
# multiple extensions
perl -e 's/(?:\.[^\.]*){2}$/rename $_, uc($`) . $&/e for @ARGV' *.tar.gz
使用BASH4:
# single extension
for i in *.txt; do j="${i%.txt}"; mv "$i" "${j^^}.txt"; done
# multiple extensions
for i in *.tar.gz; do j="${i%.tar.gz}"; mv "$i" "${j^^}.tar.gz"; done
# using a var to store the extension:
e='.tar.gz'; for i in *${e}; do j="${i%${e}}"; mv "$i" "${j^^}${e}"; done
使用GNU awk:
for i in *.txt; do
mv "$i" $(echo "$i" | awk '{ sub(/.txt$/,""); print toupper($0) ".txt" }');
done
使用GNU sed:
for i in *.txt; do
mv "$i" $(echo "$i" | sed -r -e 's/.*/\U&/' -e 's/\.TXT$/\u.txt/');
done
使用BASH3.2:
for i in *.txt; do
stem="${i%.txt}";
for ((j=0; j<"${#stem}"; j++)); do
chr="${stem:$j:1}"
if [[ "$chr" == [a-z] ]]; then
chr=$(printf "%o" "'$chr")
chr=$((chr - 40))
chr=$(printf '\'"$chr")
fi
out+="$chr"
done
mv "$i" "$out.txt"
out=
done
通常,对于小写/大写修改,经常使用“tr”(翻译字符)实用程序,它来自用于字符替换的命令行实用程序集。
dtpwmbp:~ pwadas$ echo "xxx" | tr '[a-z]' '[A-Z]'
XXX
dtpwmbp:~ pwadas$
此外,对于重命名文件,还有 perl ( man rename ) 提供的“rename”实用程序。
SYNOPSIS
rename [ -v ] [ -n ] [ -f ] perlexpr [ files ]
DESCRIPTION
"rename" renames the filenames supplied according to the rule specified as the first argument. The perlexpr argument is a Perl expression which is expected to modify the $_ string in
Perl for at least some of the filenames specified. If a given filename is not modified by the expression, it will not be renamed. If no filenames are given on the command line,
filenames will be read via standard input.
For example, to rename all files matching "*.bak" to strip the extension, you might say
rename 's/\.bak$//' *.bak
To translate uppercase names to lower, you'd use
rename 'y/A-Z/a-z/' *
我建议使用rename
,如果您只想大写文件名而不是扩展名,请使用以下内容:
rename -n 's/^([^.]*)\.(.*)$/\U$1\E.$2/' *
\U
大写所有直到\E
,请参阅perlreref(1)。-n
当您对输出感到满意时删除。
for f in *.txt; do
mv "$f" "`tr [:lower:] [:upper:] <<< "${f%.*}"`.txt"
done
Bash 4 参数扩展可以执行大小写更改:
for i in *.txt; do
i="${i%.txt}"
mv "$i.txt" "${i^^?}.txt"
done
重击:
for f in *.txt; do
no_ext=${f%.txt}
mv "$f" "${no_ext^^}.txt"
done
一种更简单、轻量级和便携的方法是:
for i in *.txt
do
fname=$(echo $i | cut -d"." -f1 | tr [a-z] [A-Z])
ext=$(echo $i | cut -d"." -f2)
mv $i $fname.$ext
done
这几乎适用于 BASH 的每个版本,因为我们使用的是每个 Unix 风格中最常见的外部实用程序(cut、tr)。
只需使用(在终端上):
for i in *.txt; do mv $i `echo ${i%.*} | tr [:lower:] [:upper:]`.txt; done;
这可能对您有用(GNU sed):
printf "%s\n" *.txt | sed 'h;s/[^.]*/\U&/;H;g;s/\(.*\)\n/mv -v \1 /' | sh
或更简单地说:
printf "%s\n" *.txt | sed 'h;s/[^.]*/\U&/;H;g;s/\(.*\)\n/mv -v \1 /e'
for i in *.jar; do mv $i `echo ${i%} | tr [:upper:] [:lower:]`; done;
这对我有用。